home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / ccr.zip / ADV.T next >
Text File  |  1993-01-23  |  107KB  |  3,689 lines

  1. /* $Header$ */
  2. /* Copyright (c) 1988, 1991 by Michael J. Roberts.  All Rights Reserved. */
  3. /*
  4.    adv.t  - standard adventure definitions for TADS games
  5.    Version 2.0
  6.  
  7.    This file is part of TADS:  The Text Adventure Development System.
  8.    Please see the file LICENSE.DOC (which should be part of the TADS
  9.    distribution) for information on using this file, and for information
  10.    on reaching High Energy Software, the developers of TADS.
  11.  
  12.    This file defines the basic classes and functions used by most TADS
  13.    adventure games.  It is generally #include'd at the start of each game
  14.    source file.
  15. */
  16.  
  17. /*
  18.  *   Define compound prepositions.  Since prepositions that appear in
  19.  *   parsed sentences must be single words, we must define any logical
  20.  *   prepositions that consist of two or more words here.  Note that
  21.  *   only two words can be pasted together at once; to paste more, use
  22.  *   a second step.  For example,  'out from under' must be defined in
  23.  *   two steps:
  24.  *
  25.  *     compoundWord 'out' 'from' 'outfrom';
  26.  *     compoundWord 'outfrom' 'under' 'outfromunder';
  27.  *
  28.  *   Listed below are the compound prepositions that were built in to
  29.  *   version 1.0 of the TADS run-time.
  30.  */
  31. compoundWord 'on' 'to' 'onto';           /* on to --> onto */
  32. compoundWord 'in' 'to' 'into';           /* in to --> into */
  33. compoundWord 'in' 'between' 'inbetween'; /* and so forth */
  34. compoundWord 'down' 'in' 'downin';
  35. compoundWord 'down' 'on' 'downon';
  36. compoundWord 'up' 'on' 'upon';
  37. compoundWord 'out' 'of' 'outof';
  38. compoundWord 'off' 'of' 'offof';
  39.  
  40. /*
  41.  *   Format strings:  these associate keywords with properties.  When
  42.  *   a keyword appears in output between percent signs (%), the matching
  43.  *   property of the current command's actor is evaluated and substituted
  44.  *   for the keyword (and the percent signs).  For example, if you have:
  45.  *
  46.  *      formatstring 'you' fmtYou;
  47.  *
  48.  *   and the command being processed is:
  49.  *
  50.  *      fred, pick up the paper
  51.  *
  52.  *   and the "fred" actor has fmtYou = "he", and this string is output:
  53.  *
  54.  *      "%You% can't see that here."
  55.  *
  56.  *   Then the actual output is:  "He can't see that here."
  57.  *
  58.  *   The format strings are chosen to look like normal output (minus the
  59.  *   percent signs, of course) when the actor is Me.
  60.  */
  61. formatstring 'you' fmtYou;
  62. formatstring 'your' fmtYour;
  63. formatstring 'you\'re' fmtYoure;
  64. formatstring 'youm' fmtYoum;
  65. formatstring 'you\'ve' fmtYouve;
  66. formatstring 's' fmtS;
  67. formatstring 'es' fmtEs;
  68. formatstring 'have' fmtHave;
  69. formatstring 'do' fmtDo;
  70. formatstring 'are' fmtAre;
  71.  
  72. /*
  73.  *   Forward-declare functions.  This is not required in most cases,
  74.  *   but it doesn't hurt.  Providing these forward declarations ensures
  75.  *   that the compiler knows that we want these symbols to refer to
  76.  *   functions rather than objects.
  77.  */
  78. checkDoor: function;
  79. checkReach: function;
  80. itemcnt: function;
  81. listcont: function;
  82. listcontcont: function;
  83. turncount: function;
  84. addweight: function;
  85. addbulk: function;
  86. incscore: function;
  87. silent_incscore: function;    // DMB
  88. darkTravel: function;
  89. scoreRank: function;
  90. terminate: function;
  91. die: function;
  92. init: function;
  93. pardon: function;
  94. preinit: function;
  95. initSearch: function;
  96.  
  97. /*
  98.  *   checkDoor:  if the door d is open, this function silently returns
  99.  *   the room r.  Otherwise, print a message ("The door is closed.") and
  100.  *   return nil.
  101.  */
  102. checkDoor: function( d, r )
  103. {
  104.     if ( d.isopen ) return( r );
  105.     else
  106.     {
  107.         setit( d );
  108.     caps(); d.thedesc; " is closed. ";
  109.     return( nil );
  110.     }
  111. }
  112.  
  113. /*
  114.  *   checkReach:  determines whether the object obj can be reached by
  115.  *   actor in location loc, using the verb v.  This routine returns true
  116.  *   if obj is a special object (numObj or strObj), if obj is in actor's
  117.  *   inventory or actor's location, or if it's in the 'reachable' list
  118.  *   for loc.
  119.  */
  120. checkReach: function( loc, actor, v, obj )
  121. {
  122.     if ( obj=numObj or obj=strObj ) return;
  123.     if ( not ( actor.isCarrying( obj ) or obj.isIn( actor.location )))
  124.     {
  125.         if (find( loc.reachable, obj ) <> nil ) return;
  126.         "%You% can't reach "; obj.thedesc; " from "; loc.thedesc; ". ";
  127.         exit;
  128.     }
  129. }
  130.  
  131. /*
  132. @itemcnt: function( list )
  133. Returns a count of the ``listable'' objects in \it list\.  An
  134. object is listable (that is, it shows up in a room's description)
  135. if its \tt isListed\ property is \tt true\.  This function is
  136. useful for determining how many objects (if any) will be listed
  137. in a room's description.
  138. */
  139. itemcnt: function( list )
  140. {
  141.     local cnt, tot, i;
  142.     tot := length( list );
  143.     cnt := 0;
  144.     i := 1;
  145.     while ( i <= tot )
  146.     {
  147.         if ( list[i].isListed ) cnt := cnt+1;
  148.         i := i+1;
  149.     }
  150.     return( cnt );
  151. }
  152.  
  153. /*
  154. @listcont: function( obj )
  155. This function displays the contents of an object, separated by
  156. commas.  The \tt thedesc\ properties of the contents are used.
  157. It is up to the caller to provide the introduction to the list
  158. (usually something to the effect of ``The box contains'' is
  159. displayed before calling \tt listcont\) and finishing the
  160. sentence (usually by displaying a period).  An object is listed
  161. only if its \tt isListed\ property is \tt true\.
  162. */
  163. listcont: function( obj )
  164. {
  165.     local i, count, tot, list, cur, disptot;
  166.     count := 0;
  167.     list := obj.contents;
  168.     tot := length( list );
  169.     disptot := itemcnt( list );
  170.     i := 1;
  171.     while ( i <= tot )
  172.     {
  173.         cur := list[i];
  174.         if ( cur.isListed )
  175.         {
  176.             if ( count > 0 )
  177.             {
  178.                 if ( count+1 < disptot )
  179.                     ", ";
  180.                 else if (count = 1)
  181.                     " and ";
  182.                 else
  183.                     ", and ";
  184.             }
  185.             count := count + 1;
  186.             cur.adesc;               // list this object
  187.             if ( cur.isworn ) " (being worn)";
  188.             else if ( cur.islamp and cur.islit ) " (providing light)";
  189.         }
  190.         i := i + 1;
  191.     }
  192. }
  193.  
  194. /*
  195.  *   showcontcont:  list the contents of the object, plus the contents of
  196.  *   an fixeditem's contained by the object.  A complete sentence is shown.
  197.  *   This is an internal routine used by listcontcont and listfixedcontcont.
  198.  */
  199. // DMB added print param and return value
  200. showcontcont: function(obj, print)
  201. {
  202.     local cnt := 0;
  203.     
  204.     if (itemcnt( obj.contents ))
  205.     {
  206.         if ( obj.issurface and not obj.isqsurface )
  207.         {
  208.         cnt := cnt + itemcnt(obj.contents);
  209.         if (print) {
  210.             if (cnt > 1) {    // DMB added this check
  211.                 caps(); listcont(obj);
  212.                 " are sitting on "; obj.thedesc; ". ";
  213.             }
  214.             else {
  215.                 caps(); listcont(obj); " is sitting on ";
  216.                 obj.thedesc; ". ";
  217.             }
  218.         }
  219.         }
  220.         else if ( obj.contentsVisible and not obj.isqcontainer )
  221.         {
  222.         cnt := cnt + itemcnt(obj.contents);
  223.         if (print) {
  224.             caps();
  225.             obj.thedesc; " seems to contain ";
  226.             listcont( obj );
  227.             ". ";
  228.         }
  229.         }
  230.     }
  231.     if ( obj.contentsVisible and not obj.isqcontainer )
  232.         cnt := cnt + listfixedcontcont(obj, print);
  233.  
  234.     return cnt;
  235. }
  236.  
  237. /*
  238. @listfixedcontcont: function( obj )
  239. List the contents of the contents of any \tt fixeditem\ objects
  240. in the \tt contents\ list of the object \it obj\.  This routine
  241. makes sure that all objects that can be taken are listed somewhere
  242. in a room's description.  This routine recurses down the contents
  243. tree, following each branch until either something has been listed
  244. or the branch ends without anything being listable.  This routine
  245. displays a complete sentence, so no introductory or closing text
  246. is needed.
  247. */
  248. // DMB added print param and return value
  249. listfixedcontcont: function(obj, print)
  250. {
  251.     local list, i, tot, thisobj;
  252.     local cnt := 0;
  253.  
  254.     list := obj.contents;
  255.     tot := length( list );
  256.     i := 1;
  257.     while ( i <= tot )
  258.     {
  259.         thisobj := list[i];
  260.         if ( thisobj.isfixed and thisobj.contentsVisible and
  261.       not thisobj.isqcontainer )
  262.             cnt := cnt + showcontcont(thisobj, print);
  263.     i := i + 1;
  264.     }
  265.     return cnt;
  266. }
  267.  
  268. /*
  269. @listcontcont: function( obj )
  270. This function lists the contents of the contents of an object.
  271. It displays full sentences, so no introductory or closing text
  272. is required.  Any item in the \tt contents\ list of the object
  273. \it obj\ whose \tt contentsVisible\ property is \tt true\ has
  274. its contents listed.  An Object whose \tt isqcontainer\ or
  275. \tt isqsurface\ property is \tt true\ will not have its
  276. contents listed.
  277. */
  278. // DMB added print parameter and return value
  279. listcontcont: function(obj, print)
  280. {
  281.     local list, i, tot;
  282.     local cnt := 0;
  283.     
  284.     list := obj.contents;
  285.     tot := length( list );
  286.     i := 1;
  287.     while ( i <= tot )
  288.     {
  289.         cnt := cnt + showcontcont(list[i], print);
  290.     i := i + 1;
  291.     }
  292.     return cnt;
  293. }
  294.  
  295. /*
  296. @turncount: function( parm )
  297. This function can be used as a daemon (normally set up in the \tt init\
  298. function) to update the turn counter after each turn.  This routine
  299. increments \tt global.turnsofar\, and then calls \tt setscore\ to
  300. update the status line with the new turn count.
  301. */
  302. turncount: function( parm )
  303. {
  304.     incturn();
  305.     global.turnsofar := global.turnsofar + 1;
  306.     setscore( global.score, global.turnsofar );
  307. }
  308.                    
  309. /*
  310. @addweight: function( list )
  311. Adds the weights of the objects in \it list\ and returns the sum.
  312. The weight of an object is given by its \tt weight\ property.  This
  313. routine includes the weights of all of the contents of each object,
  314. and the weights of their contents, and so forth.
  315. */
  316. addweight: function( l )
  317. {
  318.     local tot, i, c, totweight;
  319.  
  320.     tot := length( l );
  321.     i := 1;
  322.     totweight := 0;
  323.     while ( i <= tot )
  324.     {
  325.         c := l[i];
  326.         totweight := totweight + c.weight;
  327.         if (length( c.contents ))
  328.             totweight := totweight + addweight( c.contents );
  329.         i := i + 1;
  330.     }
  331.     return( totweight );
  332. }
  333.  
  334. /*
  335. @addbulk: function( list )
  336. This function returns the sum of the bulks (given by the \tt bulk\
  337. property) of each object in \it list\.  The value returned includes
  338. only the bulk of each object in the list, and \it not\ of the contents
  339. of the objects, as it is assumed that an object does not change in
  340. size when something is put inside it.  You can easily change this
  341. assumption for special objects (such as a bag that stretches as
  342. things are put inside) by writing an appropriate \tt bulk\ method
  343. for that object.
  344. */
  345. addbulk: function( list )
  346. {
  347.     local i, tot, totbulk, rem, cur;
  348.  
  349.     tot := length( list );
  350.     i := 1;
  351.     totbulk := 0;
  352.     while( i <= tot )
  353.     {
  354.         cur := list[i];
  355.         if ( not cur.isworn )
  356.             totbulk := totbulk + cur.bulk;
  357.         i := i + 1;
  358.     }
  359.     return( totbulk );
  360. }
  361.  
  362. /*
  363. @incscore: function( amount )
  364. Adds \it amount\ to the total score, and updates the status line
  365. to reflect the new score.  The total score is kept in \tt global.score\.
  366. Always use this routine rather than changing \tt global.score\
  367. directly, since this routine ensures that the status line is
  368. updated with the new value.
  369. */
  370. incscore: function( amount )    /* DMB */
  371. {
  372.     silent_incscore(amount);
  373.  
  374.     "\b";
  375.     if (amount = -1)
  376.         "* Your score just went down by a point. *";
  377.     else if (amount = 1)
  378.         "* Your score just went up by a point. *";
  379.     else if (amount < -1) {
  380.         "* Your score just went down by ";
  381.         say(-1 * amount); " points. *";
  382.     }
  383.     else if (amount > 1) {
  384.         "* Your score just went up by "; say(amount); " points. *";
  385.     }
  386.     "\b";
  387. }
  388. // DMB: added the following:
  389. silent_incscore: function( amount )
  390. {
  391.     global.score := global.score + amount;
  392.     setscore( global.score, global.turnsofar );
  393. }
  394.  
  395. /*
  396. @initSearch: function
  397. Initializes the containers of objects with a \tt searchLoc\, \tt underLoc\,
  398. and \tt behindLoc\ by setting up \tt searchCont\, \tt underCont\, and
  399. \tt behindCont\ lists, respectively.  You should call this function once in
  400. your \tt preinit\ (or \tt init\, if you prefer) function to ensure that
  401. the underable, behindable, and searchable objects are set up correctly.
  402. */
  403. initSearch: function
  404. {
  405.     local o;
  406.     
  407.     o := firstobj(hiddenItem);
  408.     while (o <> nil)
  409.     {
  410.     if (o.searchLoc)
  411.         o.searchLoc.searchCont := o.searchLoc.searchCont + o;
  412.     else if (o.underLoc)
  413.         o.underLoc.underCont := o.underLoc.underCont + o;
  414.     else if (o.behindLoc)
  415.         o.behindLoc.behindCont := o.behindLoc.behindCont + o;
  416.     o := nextobj(o, hiddenItem);
  417.     }
  418. }
  419.  
  420. /*
  421. @nestedroom: room
  422. A special kind of room that is inside another room; chairs and
  423. some types of vehicles, such as inflatable rafts, fall into this
  424. category.  Note that a room can be within another room without
  425. being a \tt nestedroom\, simply by setting its \tt location\ property
  426. to another room.  The \tt nestedroom\ is different from an ordinary
  427. room, though, in that it's an ``open'' room; that is, when inside it,
  428. the actor is still really inside the enclosing room for purposes of
  429. descriptions.  Hence, the player sees ``Laboratory, in the chair."
  430. In addition, a \tt nestedroom\ is an object in its own right,
  431. visible to the player; for example, a chair is an object in a
  432. room in addition to being a room itself.
  433. */
  434. class nestedroom: room
  435.     islit =
  436.     {
  437.         if ( self.location ) return( self.location.islit );
  438.         return( nil );
  439.     }
  440.     statusLine = {
  441.              /* DMB onword */
  442.            self.location.sdesc; ", ";
  443.            self.onword; " "; 
  444.            self.thedesc; "\n\t";
  445.     }
  446.     lookAround( verbosity ) =
  447.     {
  448.         self.statusLine;
  449.     self.location.nrmLkAround( verbosity );
  450.     }
  451.     roomDrop( obj ) =
  452.     {
  453.         if ( self.location = nil or self.isdroploc ) pass roomDrop;
  454.     else self.location.roomDrop( obj );
  455.     }
  456. ;
  457.  
  458. /*
  459. @chairitem: fixeditem, nestedroom, surface
  460. Acts like a chair:  actors can sit on the object.  While sitting
  461. on the object, an actor can't go anywhere until standing up, and
  462. can only reach objects that are on the chair and in the chair's
  463. \tt reachable\ list.  By default, nothing is in the \tt reachable\
  464. list.  Note that there is no real distinction made between chairs
  465. and beds, so you can sit or lie on either; the only difference is
  466. the message displayed describing the situation.
  467. */
  468. class chairitem: fixeditem, nestedroom, surface
  469.     /* DMB onroom */
  470.     onword = { if (self.onroom) "on"; else "in"; }
  471.     offword = { if (self.onroom) "off"; else "out"; }
  472.  
  473.     reachable = []          // list of all containers reachable from here;
  474.                             //  normally, you can only reach carried items
  475.                             //  from a chair, but this makes special allowances
  476.     ischair = true          // it is a chair by default; for beds or other
  477.                             //  things you lie down on, make it false
  478.     roomAction( actor, v, dobj, prep, io ) =
  479.     {
  480.         if ( dobj<>nil and v<>inspectVerb )
  481.             checkReach( self, actor, v, dobj );
  482.         if ( io<>nil and v<>askVerb and v<>tellVerb )
  483.             checkReach( self, actor, v, io );
  484.     pass roomAction;
  485.     }
  486.     enterRoom( actor ) = {}
  487.     noexit =
  488.     {
  489.         "%You're% not going anywhere until %you% get%s% ";
  490.     self.offword; " of"; self.thedesc; ". ";
  491.         return( nil );
  492.     }
  493.     verDoBoard( actor ) = { self.verDoSiton( actor ); }
  494.     doBoard( actor ) = { self.doSiton( actor ); }
  495.     verDoSiton( actor ) =
  496.     {
  497.         if ( actor.location = self )
  498.         {
  499.             "%You're% already "; self.onword; " ";
  500.             self.thedesc; "! ";
  501.         }
  502.     }
  503.     doSiton( actor ) =
  504.     {
  505.         "Okay, %you're% now sitting "; self.onword; " "; self.thedesc; ". ";
  506.         actor.travelTo( self );
  507.     }
  508.     verDoLieon( actor ) =
  509.     {
  510.         self.verDoSiton( actor );
  511.     }
  512.     doLieon( actor ) =
  513.     {
  514.         // DMB changed so it says "lying"
  515.         "Okay, %you're% now lying "; self.onword; " "; self.thedesc; ". ";
  516.         actor.travelTo(self);
  517.     }
  518.     // DMB: added the following:
  519.     doUnboard( actor ) =
  520.     {
  521.         if ( self.fastenitem )
  522.     {
  523.         "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
  524.         " first. ";
  525.     }
  526.     else
  527.     {
  528.             "Okay, %you're% no longer "; self.onword; " "; self.thedesc; ". ";
  529.             self.leaveRoom( actor );
  530.         actor.moveInto( self.location );
  531.     }
  532.     }
  533. ;
  534.  
  535. /*
  536. @beditem: chairitem
  537. This object is the same as a \tt chairitem\, except that the player
  538. is described as lying on, rather than sitting in, the object.
  539. */
  540. class beditem: chairitem
  541.     onroom = true
  542.     ischair = nil
  543.     isbed = true
  544.     sdesc = "bed"
  545. ;
  546.  
  547. /*
  548. @thing: object
  549. The basic class for objects in a game.  The property \tt contents\
  550. is a list that specifies what is in the object; this property is
  551. automatically set up by the system after the game is compiled to
  552. contain a list of all objects that have this object as their
  553. \tt location\ property.  The \tt contents\ property is kept
  554. consistent with the \tt location\ properties of referenced objects
  555. by the \tt moveInto\ method; always use \tt moveInto\ rather than
  556. directly setting a \tt location\ property for this reason.  The
  557. \tt adesc\ method displays the name of the object with an indefinite
  558. article; the default is to display ``a'' followed by the \tt sdesc\,
  559. but objects that need a different indefinite article (such as ``an''
  560. or ``some'') should override this method.  Likewise, \tt thedesc\
  561. displays the name with a definite article; by default, \tt thedesc\
  562. displays ``the'' followed by the object's \tt sdesc\.  The \tt sdesc\
  563. simply displays the object's name (``short description'') without
  564. any articles.  The \tt ldesc\ is the long description, normally
  565. displayed when the object is examined by the player; by default,
  566. the \tt ldesc\ displays a ``It looks like an ordinary \tt sdesc\.''
  567. The \tt isIn( \it object\ )\ method returns \tt true\ if the
  568. object's location is the specified \it object\ or the object's
  569. \tt location\ is an object whose \tt contentsVisible\ property is
  570. \tt true\ and that object's \tt isIn( \it object\ )\ method is
  571. \tt true\.  Note that if \tt isIn\ is \tt true\, it doesn't
  572. necessarily mean the object is reachable, because \tt isIn\ is
  573. \tt true\ if the object is merely visible within the location.
  574. The \tt thrudesc\ method displays a message for when the
  575. player looks through the object (objects such as windows would
  576. use this property).  The \tt moveInto( \it object\ )\ method
  577. moves the object to be inside the specified \it object\; always use
  578. \tt moveInto\ to move an object rather than setting its \tt location\
  579. directly, so that the appropriate \tt contents\ lists are updated.
  580. To make an object disappear, move it into \tt nil\.
  581. */
  582. class thing: object
  583.     isListed = true         // shows up in room/inventory listings
  584.     contents = []           // set up automatically by system - do not set
  585.     verGrab( obj ) = {}
  586.     Grab( obj ) = {}
  587.     adesc =
  588.     {
  589.         "a "; self.sdesc;   // default is "a <name>"; "self" is current object
  590.     }
  591.     thedesc =
  592.     {
  593.         "the "; self.sdesc; // default is "the <name>"
  594.     }
  595.     ldesc = { "It looks like an ordinary "; self.sdesc; " to me."; }
  596.     readdesc = { "%You% can't read "; self.adesc; ". "; }
  597.     actorAction( v, d, p, i ) =
  598.     {
  599.         "You have lost your mind. ";
  600.         exit;
  601.     }
  602.     contentsVisible = { return( true ); }
  603.     contentsReachable = { return( true ); }
  604.     isIn( obj ) =
  605.     {
  606.         local myloc;
  607.  
  608.         myloc := self.location;
  609.         if ( myloc )
  610.         {
  611.             if ( myloc = obj ) return( true );
  612.             if ( myloc.contentsVisible ) return( myloc.isIn( obj ));
  613.         }
  614.         return( nil );
  615.     }
  616.     thrudesc = { "%You% can't see much through "; self.thedesc; ".\n"; }
  617.     moveInto( obj ) =
  618.     {
  619.         local loc;
  620.  
  621.     /*
  622.      *   For the object containing me, and its container, and so forth,
  623.      *   tell it via a Grab message that I'm going away.
  624.      */
  625.     loc := self.location;
  626.     while ( loc )
  627.     {
  628.         loc.Grab( self );
  629.         loc := loc.location;
  630.     }
  631.  
  632.         if ( self.location )
  633.             self.location.contents := self.location.contents - self;
  634.         self.location := obj;
  635.         if ( obj ) obj.contents := obj.contents + self;
  636.     }
  637.     verDoSave( actor ) =
  638.     {
  639.         "Please specify the name of the game to save in double quotes,
  640.         for example, SAVE \"GAME1\". ";
  641.     }
  642.     verDoRestore( actor ) =
  643.     {
  644.         "Please specify the name of the game to restore in double quotes,
  645.         for example, SAVE \"GAME1\". ";
  646.     }
  647.     verDoScript( actor ) =
  648.     {
  649.         "You should type the name of a file to write the transcript to
  650.         in quotes, for example, SCRIPT \"LOG1\". ";
  651.     }
  652.     verDoSay( actor ) =
  653.     {
  654.         "You should say what you want to say in double quotes, for example,
  655.         SAY \"HELLO\". ";
  656.     }
  657.     verDoPush( actor ) =
  658.     {
  659.         "Pushing "; self.thedesc; " doesn't do anything. ";
  660.     }
  661.     verDoWear( actor ) =
  662.     {
  663.         "%You% can't wear "; self.thedesc; ". ";
  664.     }
  665.     verDoTake( actor ) =
  666.     {
  667.         if ( self.location = actor )
  668.         {
  669.             "%You% already %have% "; self.thedesc; "! ";
  670.         }
  671.         else self.verifyRemove( actor );
  672.     }
  673.     verifyRemove( actor ) =
  674.     {
  675.       /*
  676.      *   Check with each container to make sure that the container
  677.      *   doesn't object to the object's removal.
  678.      */
  679.         local loc;
  680.  
  681.         loc := self.location;
  682.         while ( loc )
  683.         {
  684.             if ( loc <> actor ) loc.verGrab( self );
  685.             loc := loc.location;
  686.         }
  687.     }
  688.     isVisible( vantage ) =
  689.     {
  690.         local loc;
  691.  
  692.         loc := self.location;
  693.         if ( loc = nil ) return( nil );
  694.  
  695.         /* if it's in the vantage, it's visible */
  696.         if ( loc = vantage ) return( true );
  697.  
  698.         /*
  699.          *   if its location's contents are visible, and its location is
  700.          *   itself visible, it's visible
  701.          */
  702.         if ( loc.contentsVisible and loc.isVisible( vantage )) return( true );
  703.  
  704.         /*
  705.          *   If the vantage has a location, and the vantage's location's
  706.          *   contents are visible (if you can see me I can see you), and
  707.          *   the object is visible from the vantage's location, the object
  708.          *   is visible
  709.          */
  710.         if ( vantage.location <> nil and vantage.location.contentsVisible and
  711.          self.isVisible( vantage.location ))
  712.             return( true );
  713.  
  714.         /* all tests failed:  it's not visible */
  715.         return( nil );
  716.     }
  717.     cantReach( actor ) =
  718.     {
  719.         if ( self.location = nil )
  720.         {
  721.             if ( actor.location.location )
  722.                "%You% can't reach that from << actor.location.thedesc >>. ";
  723.             return;
  724.         }
  725.         if ( not self.location.isopenable or self.location.isopen )
  726.             self.location.cantReach( actor );
  727.         else "%You%'ll have to open << self.location.thedesc >> first. ";
  728.     }
  729.     isReachable( actor ) =
  730.     {
  731.         local loc;
  732.  
  733.         /* if the object is in the room's 'reachable' list, it's reachable */
  734.         if (find( actor.location.reachable, self ) <> nil )
  735.             return( true );
  736.  
  737.         /*
  738.          *   If the object's container's contents are reachable, and the
  739.          *   container is reachable, the object is reachable.
  740.          */
  741.         loc := self.location;
  742.     if (find( actor.location.reachable, self ) <> nil )
  743.         return( true );
  744.     if ( loc = nil ) return( nil );
  745.     if ( loc = actor or loc = actor.location ) return( true );
  746.     if ( loc.contentsReachable )
  747.         return( loc.isReachable( actor ));
  748.     return( nil );
  749.         return( nil );
  750.     }
  751.     doTake( actor ) =
  752.     {
  753.         local totbulk, totweight;
  754.  
  755.         totbulk := addbulk( actor.contents ) + self.bulk;
  756.         totweight := addweight( actor.contents );
  757.         if ( not actor.isCarrying( self ))
  758.             totweight := totweight + self.weight;
  759.  
  760.         if ( totweight > actor.maxweight )
  761.             "%Your% load is too heavy. ";
  762.         else if ( totbulk > actor.maxbulk )
  763.             "%You've% already got %your% hands full. ";
  764.         else
  765.         {
  766.             self.moveInto( actor );
  767.             "Taken. ";
  768.         }
  769.     }
  770.     verDoDrop( actor ) =
  771.     {
  772.         if ( not actor.isCarrying( self ))
  773.         {
  774.             "%You're% not carrying "; self.thedesc; "! ";
  775.         }
  776.         else self.verifyRemove( actor );
  777.     }
  778.     doDrop( actor ) =
  779.     {
  780.         actor.location.roomDrop( self );
  781.     }
  782.     verDoUnwear( actor ) =
  783.     {
  784.         "%You're% not wearing "; self.thedesc; "! ";
  785.     }
  786.     verIoPutIn( actor ) =
  787.     {
  788.         "I don't know how to put anything into "; self.thedesc; ". ";
  789.     }
  790.     verDoPutIn( actor, io ) =
  791.     {
  792.         if ( io = nil ) return;
  793.  
  794.         if ( self.location = io )
  795.         {
  796.             caps(); self.thedesc; " is already in "; io.thedesc; "! ";
  797.         }
  798.         else if ( io = self or io.isIn( self ))
  799.         {
  800.             "%You% can't put "; self.thedesc; " in itself! ";
  801.         }
  802.         else self.verifyRemove( actor );
  803.     }
  804.     doPutIn( actor, io ) =
  805.     {
  806.         self.moveInto( io );
  807.         "Done. ";
  808.     }
  809.     verIoPutOn( actor ) =
  810.     {
  811.         "There's no good surface on "; self.thedesc; ". ";
  812.     }
  813.     verDoPutOn( actor, io ) =
  814.     {
  815.         if ( io = nil ) return;
  816.  
  817.         if ( self.location = io )
  818.         {
  819.             caps(); self.thedesc; " is already on "; io.thedesc; "! ";
  820.         }
  821.         else if ( io = self or io.isIn( self ))
  822.         {
  823.             "%You% can't put "; self.thedesc; " on itself! ";
  824.         }
  825.         else self.verifyRemove( actor );
  826.     }
  827.     doPutOn( actor, io ) =
  828.     {
  829.         self.moveInto( io );
  830.         "Done. ";
  831.     }
  832.     verIoTakeOut( actor ) = {}
  833.     ioTakeOut( actor, dobj ) =
  834.     {
  835.         dobj.doTakeOut( actor, self );
  836.     }
  837.     verDoTakeOut( actor, io ) =
  838.     {
  839.         if ( io <> nil and not self.isIn( io ))
  840.         {
  841.             caps(); self.thedesc; " isn't in "; io.thedesc; ". ";
  842.         }
  843.     self.verDoTake(actor);         /* ensure object can be taken at all */
  844.     }
  845.     doTakeOut( actor, io ) =
  846.     {
  847.         self.doTake( actor );
  848.     }
  849.     verIoTakeOff( actor ) = {}
  850.     ioTakeOff( actor, dobj ) =
  851.     {
  852.         dobj.doTakeOff( actor, self );
  853.     }
  854.     verDoTakeOff( actor, io ) =
  855.     {
  856.         if ( io <> nil and not self.isIn( io ))
  857.         {
  858.             caps(); self.thedesc; " isn't on "; io.thedesc; "! ";
  859.         }
  860.     self.verDoTake(actor);         /* ensure object can be taken at all */
  861.     }
  862.     doTakeOff( actor, io ) =
  863.     {
  864.         self.doTake( actor );
  865.     }
  866.     verIoPlugIn( actor ) =
  867.     {
  868.         "%You% can't plug anything into "; self.thedesc; ". ";
  869.     }
  870.     verDoPlugIn( actor, io ) =
  871.     {
  872.         "%You% can't plug "; self.thedesc; " into anything. ";
  873.     }
  874.     verIoUnplugFrom( actor ) =
  875.     {
  876.         "It's not plugged into "; self.thedesc; ". ";
  877.     }
  878.     verDoUnplugFrom( actor, io ) =
  879.     {
  880.         if ( io <> nil ) { "It's not plugged into "; io.thedesc; ". "; }
  881.     }
  882.     verDoLookin( actor ) =
  883.     {
  884.         "There's nothing in "; self.thedesc; ". ";
  885.     }
  886.     verDoLookthru( actor ) =
  887.     {
  888.         "%You% can't see anything through "; self.thedesc; ". ";
  889.     }
  890.     verDoLookunder( actor ) =
  891.     {
  892.         "There's nothing under "; self.thedesc; ". ";
  893.     }
  894.     verDoInspect( actor ) = {}
  895.     doInspect( actor ) =
  896.     {
  897.         self.ldesc;
  898.     }
  899.     verDoRead( actor ) =
  900.     {
  901.         "I don't know how to read "; self.thedesc; ". ";
  902.     }
  903.     verDoLookbehind( actor ) =
  904.     {
  905.         "There's nothing behind "; self.thedesc; ". ";
  906.     }
  907.     verDoTurn( actor ) =
  908.     {
  909.         "Turning "; self.thedesc; " doesn't have any effect. ";
  910.     }
  911.     verDoTurnWith( actor, io ) =
  912.     {
  913.         "Turning "; self.thedesc; " doesn't have any effect. ";
  914.     }
  915.     verDoTurnTo( actor, io ) =
  916.     {
  917.         "Turning "; self.thedesc; " doesn't have any effect. ";
  918.     }
  919.     verIoTurnTo( actor ) =
  920.     {
  921.         "I don't know how to do that. ";
  922.     }
  923.     verDoTurnon( actor ) =
  924.     {
  925.         "I don't know how to turn "; self.thedesc; " on. ";
  926.     }
  927.     verDoTurnoff( actor ) =
  928.     {
  929.         "I don't know how to turn "; self.thedesc; " off. ";
  930.     }
  931.     verIoAskAbout( actor ) = {}
  932.     ioAskAbout( actor, dobj ) =
  933.     {
  934.         dobj.doAskAbout( actor, self );
  935.     }
  936.     verDoAskAbout( actor, io ) =
  937.     {
  938.         "Surely, %you% can't think "; self.thedesc; " knows anything
  939.         about it! ";
  940.     }
  941.     verIoTellAbout( actor ) = {}
  942.     ioTellAbout( actor, dobj ) =
  943.     {
  944.         dobj.doTellAbout( actor, self );
  945.     }
  946.     verDoTellAbout( actor, io ) =
  947.     {
  948.         "It doesn't look as though "; self.thedesc; " is interested. ";
  949.     }
  950.     verDoUnboard( actor ) =
  951.     {
  952.         if ( actor.location <> self )
  953.         {
  954.             "%You're% not in "; self.thedesc; "! ";
  955.         }
  956.         else if ( self.location=nil )
  957.         {
  958.             "%You% can't get out of "; self.thedesc; "! ";
  959.         }
  960.     }
  961.     doUnboard( actor ) =
  962.     {
  963.         if ( self.fastenitem )
  964.     {
  965.         "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
  966.         " first. ";
  967.     }
  968.     else
  969.     {
  970.             "Okay, %you're% no longer in "; self.thedesc; ". ";
  971.             self.leaveRoom( actor );
  972.         actor.moveInto( self.location );
  973.     }
  974.     }
  975.     verDoAttackWith( actor, io ) =
  976.     {
  977.         "Attacking "; self.thedesc; " doesn't appear productive. ";
  978.     }
  979.     verIoAttackWith( actor ) =
  980.     {
  981.         "It's not very effective to attack with "; self.thedesc; ". ";
  982.     }
  983.     verDoEat( actor ) =
  984.     {
  985.         "I think I just lost my appetite.";        // DMB
  986.     }
  987.     verDoDrink( actor ) =
  988.     {
  989.         "Don't be ridiculous!";    // DMB
  990.     }
  991.     verDoGiveTo( actor, io ) =
  992.     {
  993.         if ( not actor.isCarrying( self ))
  994.         {
  995.             "%You're% not carrying "; self.thedesc; ". ";
  996.         }
  997.         else self.verifyRemove( actor );
  998.     }
  999.     doGiveTo( actor, io ) =
  1000.     {
  1001.         self.moveInto( io );
  1002.         "Done. ";
  1003.     }
  1004.     verDoPull( actor ) =
  1005.     {
  1006.         "Pulling "; self.thedesc; " doesn't have any effect. ";
  1007.     }
  1008.     verDoThrowAt( actor, io ) =
  1009.     {
  1010.         if ( not actor.isCarrying( self ))
  1011.         {
  1012.             "%You're% not carrying "; self.thedesc; ". ";
  1013.         }
  1014.         else self.verifyRemove( actor );
  1015.     }
  1016.     doThrowAt( actor, io ) =
  1017.     {
  1018.         "%You% miss%es%. ";
  1019.         self.moveInto( actor.location );
  1020.     }
  1021.     verIoThrowAt( actor ) =
  1022.     {
  1023.         if ( actor.isCarrying( self ))
  1024.         {
  1025.             "%You% could at least drop "; self.thedesc; " first. ";
  1026.         }
  1027.     }
  1028.     ioThrowAt( actor, dobj ) =
  1029.     {
  1030.         dobj.doThrowAt( actor, self );
  1031.     }
  1032.     verDoThrowTo( actor, io ) =
  1033.     {
  1034.         if ( not actor.isCarrying( self ))
  1035.         {
  1036.             "%You're% not carrying "; self.thedesc; ". ";
  1037.         }
  1038.         else self.verifyRemove( actor );
  1039.     }
  1040.     doThrowTo( actor, io ) =
  1041.     {
  1042.         "%You% miss%es%. ";
  1043.         self.moveInto( actor.location );
  1044.     }
  1045.     verDoThrow( actor ) =
  1046.     {
  1047.         if ( not actor.isCarrying( self ))
  1048.         {
  1049.             "%You're% not carrying "; self.thedesc; ". ";
  1050.         }
  1051.         else self.verifyRemove( actor );
  1052.     }
  1053.     doThrow( actor ) =
  1054.     {
  1055.         "Thrown. ";
  1056.         self.moveInto( actor.location );
  1057.     }
  1058.     verDoShowTo( actor, io ) =
  1059.     {
  1060.     }
  1061.     doShowTo( actor, io ) =
  1062.     {
  1063.         if ( io <> nil ) { caps(); io.thedesc; " isn't impressed. "; }
  1064.     }
  1065.     verIoShowTo( actor ) =
  1066.     {
  1067.         caps(); self.thedesc; " isn't impressed. ";
  1068.     }
  1069.     verDoClean( actor ) =
  1070.     {
  1071.         caps(); self.thedesc; " looks a bit cleaner now. ";
  1072.     }
  1073.     verDoCleanWith( actor, io ) = {}
  1074.     doCleanWith( actor, io ) =
  1075.     {
  1076.         caps(); self.thedesc; " looks a bit cleaner now. ";
  1077.     }
  1078.     verDoMove( actor ) =
  1079.     {
  1080.         "Moving "; self.thedesc; " doesn't reveal anything. ";
  1081.     }
  1082.     verDoMoveTo( actor, io ) =
  1083.     {
  1084.         "Moving "; self.thedesc; " doesn't reveal anything. ";
  1085.     }
  1086.     verIoMoveTo( actor ) =
  1087.     {
  1088.         "That doesn't get us anywhere. ";
  1089.     }
  1090.     verDoMoveWith( actor, io ) =
  1091.     {
  1092.         "Moving "; self.thedesc; " doesn't reveal anything. ";
  1093.     }
  1094.     verIoMoveWith( actor ) =
  1095.     {
  1096.         caps(); self.thedesc; " doesn't seem to help. ";
  1097.     }
  1098.     verDoTypeOn( actor, io ) =
  1099.     {
  1100.         "You should say what you want to type in double quotes, for
  1101.         example, TYPE \"HELLO\" ON KEYBOARD. ";
  1102.     }
  1103.     verDoTouch( actor ) =
  1104.     {
  1105.         "Touching "; self.thedesc; " doesn't seem to have any effect. ";
  1106.     }
  1107.     verDoPoke( actor ) =
  1108.     {
  1109.         "Poking "; self.thedesc; " doesn't seem to have any effect. ";
  1110.     }
  1111.     genMoveDir = { "%You% can't seem to do that. "; }
  1112.     verDoMoveN( actor ) = { self.genMoveDir; }
  1113.     verDoMoveS( actor ) = { self.genMoveDir; }
  1114.     verDoMoveE( actor ) = { self.genMoveDir; }
  1115.     verDoMoveW( actor ) = { self.genMoveDir; }
  1116.     verDoMoveNE( actor ) = { self.genMoveDir; }
  1117.     verDoMoveNW( actor ) = { self.genMoveDir; }
  1118.     verDoMoveSE( actor ) = { self.genMoveDir; }
  1119.     verDoMoveSW( actor ) = { self.genMoveDir; }
  1120.     verDoSearch( actor ) =
  1121.     {
  1122.         "%You% find%s% nothing of interest. ";
  1123.     }
  1124.  
  1125. #include "thingext.t"    // DMB: include extensions to standard thing class
  1126. ;
  1127.  
  1128. /*
  1129. @item: thing
  1130. A basic item which can be picked up by the player.  It has no weight
  1131. (0) and minimal bulk (1).  The \tt weight\ property should be set
  1132. to a non-zero value for heavy objects.  The \tt bulk\ property
  1133. should be set to a value greater than 1 for bulky objects, and to
  1134. zero for objects that are very small and take essentially no effort
  1135. to hold---or, more precisely, don't detract at all from the player's
  1136. ability to hold other objects (for example, a piece of paper).
  1137. */
  1138. class item: thing
  1139.     weight = 0
  1140.     bulk = 1
  1141. ;
  1142.     
  1143. /*
  1144. @lightsource: item
  1145. A portable lamp, candle, match, or other source of light.  The
  1146. light source can be turned on and off with the \tt islit\ property.
  1147. If \tt islit\ is \tt true\, the object provides light, otherwise it's
  1148. just an ordinary object.
  1149. */
  1150. class lightsource: item
  1151.     islamp = true
  1152. ;
  1153.  
  1154. /*
  1155. @hiddenItem: object
  1156. This is an object that is hidden with one of the \tt hider\ classes. 
  1157. A \tt hiddenItem\ object doesn't have any special properties in its
  1158. own right, but all objects hidden with one of the \tt hider\ classes
  1159. must be of class \tt hiddenItem\ so that \tt initSearch\ can find
  1160. them.
  1161. */
  1162. class hiddenItem: object
  1163. ;
  1164.  
  1165. /*
  1166. @hider: item
  1167. This is a basic class of object that can hide other objects in various
  1168. ways.  The \tt underHider\, \tt behindHider\, and \tt searchHider\ classes
  1169. are examples of \tt hider\ subclasses.  The class defines
  1170. the method \tt searchObj(\it actor, list\)\, which is given the list
  1171. of hidden items contained in the object (for example, this would be the
  1172. \tt underCont\ property, in the case of a \tt underHider\), and ``finds''
  1173. the object or objects. Its action is dependent upon a couple of other
  1174. properties of the \tt hider\ object.  The \tt serialSearch\ property,
  1175. if \tt true\, indicates that items in the list are to be found one at
  1176. a time; if \tt nil\ (the default), the entire list is found on the
  1177. first try.  The \tt autoTake\ property, if \tt true\, indicates that
  1178. the actor automatically takes the item or items found; if \tt nil\, the
  1179. item or items are moved to the actor's location.  The \tt searchObj\ method
  1180. returns the \it list\ with the found object or objects removed; the
  1181. caller should assign this returned value back to the appropriate
  1182. property (for example, \tt underHider\ will assign the return value
  1183. to \tt underCont\).
  1184.  
  1185. Note that because the \tt hider\ is hiding something, this class
  1186. overrides the normal \tt verDoSearch\ method to display the
  1187. message, ``You'll have to be more specific about how you want
  1188. to search that.''  The reason is that the normal \tt verDoSearch\
  1189. message (``You find nothing of interest'') leads players to believe
  1190. that the object was exhaustively searched, and we want to avoid
  1191. misleading the player.  On the other hand, we don't want a general
  1192. search to be exhaustive for most \tt hider\ objects.  So, we just
  1193. display a message letting the player know that the search was not
  1194. enough, but we don't give away what they have to do instead.
  1195.  
  1196. The objects hidden with one of the \tt hider\ classes must be
  1197. of class \tt hiddenItem\.
  1198. */
  1199. class hider: item
  1200.     verDoSearch(actor) =
  1201.     {
  1202.     "%You%'ll have to be more specific about how %you% want%s%
  1203.     to search that. ";
  1204.     }
  1205.     searchObj(actor, list) =
  1206.     {
  1207.     local found, dest, i, tot;
  1208.  
  1209.     /* see how much we get this time */
  1210.     if (self.serialSearch)
  1211.     {
  1212.         found := [] + car(list);
  1213.         list := cdr(list);
  1214.     }
  1215.     else
  1216.     {
  1217.         found := list;
  1218.         list := nil;
  1219.     }
  1220.  
  1221.     /* figure destination */
  1222.     dest := actor;
  1223.     if (not self.autoTake) dest := dest.location;
  1224.     
  1225.     /* note what we found, and move it to destination */
  1226.     "%You% find%s% ";
  1227.     tot := length(found);
  1228.     i := 1;
  1229.     while (i <= tot)
  1230.     {
  1231.         found[i].adesc;
  1232.         if (i+1 < tot) ", ";
  1233.         else if (i = 1 and tot = 2) " and ";
  1234.         else if (i+1 = tot and tot > 2) ", and ";
  1235.         
  1236.         found[i].moveInto(dest);
  1237.         i := i + 1;
  1238.     }
  1239.  
  1240.     /* say what happened */
  1241.     if (self.autoTake) ", which %you% take%s%. ";
  1242.     else "! ";
  1243.  
  1244.     if (list<>nil and length(list)=0) list := nil;
  1245.     return(list);
  1246.     }
  1247.     serialSearch = nil             /* find everything in one try by default */
  1248.     autoTake = true               /* actor takes item when found by default */
  1249. ;
  1250.  
  1251. /*
  1252. @underHider: hider
  1253. This is an object that can have other objects placed under it.  The
  1254. objects placed under it can only be found by looking under the object;
  1255. see the description of \tt hider\ for more information.  Note that you
  1256. should set the \tt underLoc\ property of each hidden object to point
  1257. to the \tt underHider\.
  1258.  
  1259. Note that an \tt underHider\ doesn't allow the \it player\ to put anything
  1260. under the object during the game.  Instead, it's to make it easy for the
  1261. game writer to set up hidden objects while implementing the game.  All you
  1262. need to do to place an object under another object is declare the top
  1263. object as an \tt underHider\, then declare the hidden object normally,
  1264. except use \tt underLoc\ rather than \tt location\ to specify the
  1265. location of the hidden object.  The \tt behindHider\ and \tt searchHider\
  1266. objects work similarly.
  1267.  
  1268. The objects hidden with \tt underHider\ must be of class \tt hiddenItem\.
  1269. */
  1270. class underHider: hider
  1271.     underCont = []         /* list of items under me (set up by initSearch) */
  1272.     verDoLookunder(actor) = {}
  1273.     doLookunder(actor) =
  1274.     {
  1275.     if (self.underCont = nil)
  1276.         "There's nothing else under <<self.thedesc>>. ";
  1277.     else
  1278.         self.underCont := self.searchObj(actor, self.underCont);
  1279.     }
  1280. ;
  1281.  
  1282. /*
  1283. @behindHider: hider
  1284. This is just like an \tt underHider\, except that objects are hidden
  1285. behind this object.  Objects to be behind this object should have their
  1286. \tt behindLoc\ property set to point to this object.
  1287.  
  1288. The objects hidden with \tt behindHider\ must be of class \tt hiddenItem\.
  1289. */
  1290. class behindHider: hider
  1291.     behindCont = []
  1292.     verDoLookbehind(actor) = {}
  1293.     doLookbehind(actor) =
  1294.     {
  1295.     if (self.behindCont = nil)
  1296.         "There's nothing else behind <<self.thedesc>>. ";
  1297.     else
  1298.         self.behindCont := self.searchObj(actor, self.behindCont);
  1299.     }
  1300. ;
  1301.     
  1302. /*
  1303. @searchHider: hider
  1304. This is just like an \tt underHider\, except that objects are hidden
  1305. within this object in such a way that the object must be looked in
  1306. or searched.  Objects to be hidden in this object should have their
  1307. \tt searchLoc\ property set to point to this object.  Note that this
  1308. is different from a normal container, in that the objects hidden within
  1309. this object will not show up until the object is explicitly looked in
  1310. or searched.
  1311.  
  1312. The items hidden with \tt searchHider\ must be of class \tt hiddenItem\.
  1313. */
  1314. class searchHider: hider
  1315.     searchCont = []
  1316.     verDoSearch(actor) = {}
  1317.     doSearch(actor) =
  1318.     {
  1319.     if (self.searchCont = nil)
  1320.         "There's nothing else in <<self.thedesc>>. ";
  1321.     else
  1322.         self.searchCont := self.searchObj(actor, self.searchCont);
  1323.     }
  1324.     verDoLookin(actor) =
  1325.     {
  1326.     if (self.searchCont = nil)
  1327.         pass verDoLookin;
  1328.     }
  1329.     doLookin(actor) =
  1330.     {
  1331.     if (self.searchCont = nil)
  1332.         pass doLookin;
  1333.     else
  1334.         self.searchCont := self.searchObj(actor, self.searchCont);
  1335.     }
  1336. ;
  1337.     
  1338.  
  1339. /*
  1340. @fixeditem: thing
  1341. An object that cannot be taken or otherwise moved from its location.
  1342. Note that a \tt fixeditem\ is sometimes part of a movable object;
  1343. this can be done to make one object part of another, ensuring that
  1344. they cannot be separated.  By default, the functions that list a room's
  1345. contents do not automatically describe \tt fixeditem\ objects (because
  1346. the \tt isListed\ property is set to \tt nil\).  Instead, the game author
  1347. will generally describe the \tt fixeditem\ objects separately as part of
  1348. the room's \tt ldesc\.  
  1349. */
  1350. class fixeditem: thing      // An immovable object
  1351.     isListed = nil          // not listed in room/inventory displays
  1352.     isfixed = true          // Item can't be taken
  1353.     weight = 0              // no actual weight
  1354.     bulk = 0
  1355.     verDoTake( actor ) =
  1356.     {
  1357.         "%You% can't have "; self.thedesc; ". ";
  1358.     }
  1359.     verDoTakeOut( actor, io ) =
  1360.     {
  1361.         self.verDoTake( actor );
  1362.     }
  1363.     verDoDrop( actor ) =
  1364.     {
  1365.         "%You% can't drop "; self.thedesc; ". ";
  1366.     }
  1367.     verDoTakeOff( actor, io ) =
  1368.     {
  1369.         self.verDoTake( actor );
  1370.     }
  1371.     verDoPutIn( actor, io ) =
  1372.     {
  1373.         "%You% can't put "; self.thedesc; " anywhere. ";
  1374.     }
  1375.     verDoPutOn( actor, io ) =
  1376.     {
  1377.         "%You% can't put "; self.thedesc; " anywhere. ";
  1378.     }
  1379.     verDoMove( actor ) =
  1380.     {
  1381.         "%You% can't move "; self.thedesc; ". ";
  1382.     }
  1383. ;
  1384.  
  1385. /*
  1386. @readable: item
  1387. An item that can be read.  The \tt readdesc\ property is displayed
  1388. when the item is read.  By default, the \tt readdesc\ is the same
  1389. as the \tt ldesc\, but the \tt readdesc\ can be overridden to give
  1390. a different message.
  1391. */
  1392. class readable: item
  1393.     verDoRead( actor ) =
  1394.     {
  1395.     }
  1396.     doRead( actor ) =
  1397.     {
  1398.         self.readdesc;
  1399.     }
  1400.     readdesc =
  1401.     {
  1402.         self.ldesc;
  1403.     }
  1404. ;
  1405.  
  1406. /*
  1407. @fooditem: item
  1408. An object that can be eaten.  When eaten, the object is removed from
  1409. the game, and \tt global.lastMealTime\ is decremented by the
  1410. \tt foodvalue\ property.  By default, the \tt foodvalue\ property
  1411. is \tt global.eatTime\, which is the time between meals.  So, the
  1412. default \tt fooditem\ will last for one ``nourishment interval.''
  1413. */
  1414. class fooditem: item
  1415.     verDoEat( actor ) =
  1416.     {
  1417.         self.verifyRemove( actor );
  1418.     }
  1419.     doEat( actor ) =
  1420.     {
  1421.         "That was delicious! ";
  1422.         global.lastMealTime := global.lastMealTime - self.foodvalue;
  1423.         self.moveInto( nil );
  1424.     }
  1425.     foodvalue = { return( global.eatTime ); }
  1426. ;
  1427.  
  1428. /*
  1429. @dialItem: fixeditem
  1430. This class is used for making ``dials,'' which are controls in
  1431. your game that can be turned to a range of numbers.  You must
  1432. define the property \tt maxsetting\ as a number specifying the
  1433. highest number to which the dial can be turned; the lowest number
  1434. on the dial is always 1.  The \tt setting\ property is the dial's
  1435. current setting, and can be changed by the player by typing the
  1436. command ``turn dial to \it number\.''  By default, the \tt ldesc\
  1437. method displays the current setting.
  1438. */
  1439. class dialItem: fixeditem
  1440.     maxsetting = 10 // it has settings from 1 to this number
  1441.     setting = 1     // the current setting
  1442.     ldesc =
  1443.     {
  1444.         caps(); self.thedesc; " can be turned to settings
  1445.         numbered from 1 to << self.maxsetting >>. It's
  1446.         currently set to << self.setting >>. ";
  1447.     }
  1448.     verDoTurn( actor ) = {}
  1449.     doTurn( actor ) =
  1450.     {
  1451.         askio( toPrep );
  1452.     }
  1453.     verDoTurnTo( actor, io ) = {}
  1454.     doTurnTo( actor, io ) =
  1455.     {
  1456.         if ( io = numObj )
  1457.         {
  1458.             if ( numObj.value < 1 or numObj.value > self.maxsetting )
  1459.             {
  1460.                 "There's no such setting! ";
  1461.             }
  1462.             else if ( numObj.value <> self.setting )
  1463.             {
  1464.                 self.setting := numObj.value;
  1465.                 "Okay, it's now turned to "; say( self.setting ); ". ";
  1466.             }
  1467.             else
  1468.             {
  1469.                 "It's already set to "; say( self.setting ); "! ";
  1470.             }
  1471.         }
  1472.         else
  1473.         {
  1474.             "I don't know how to turn "; self.thedesc;
  1475.             " to that. ";
  1476.         }
  1477.     }
  1478. ;
  1479.  
  1480. /*
  1481. @switchItem: fixeditem
  1482. This is a class for things that can be turned on and off by the
  1483. player.  The only special property is \tt isActive\, which is \tt nil\
  1484. if the switch is turned off and \tt true\ when turned on.  The object
  1485. accepts the commands ``turn it on'' and ``turn it off,'' as well as
  1486. synonymous constructions, and updates \tt isActive\ accordingly.
  1487. */
  1488. class switchItem: fixeditem
  1489.     verDoSwitch( actor ) = {}
  1490.     doSwitch( actor ) =
  1491.     {
  1492.         self.isActive := not self.isActive;
  1493.         "Okay, "; self.thedesc; " is now switched ";
  1494.         if ( self.isActive ) "on"; else "off";
  1495.         ". ";
  1496.     }
  1497.     verDoTurnon( actor ) =
  1498.     {
  1499.         if ( self.isActive ) "It's already turned on! ";
  1500.     }
  1501.     doTurnon( actor ) =
  1502.     {
  1503.         self.isActive := true;
  1504.         "Okay, it's now turned on. ";
  1505.     }
  1506.     verDoTurnoff( actor ) =
  1507.     {
  1508.         if ( not self.isActive ) "It's already turned off! ";
  1509.     }
  1510.     doTurnoff( actor ) =
  1511.     {
  1512.         self.isActive := nil;
  1513.         "Okay, it's now turned off. ";
  1514.     }
  1515. ;
  1516.  
  1517. /*
  1518. @room: thing
  1519. A location in the game.  By default, the \tt islit\ property is
  1520. \tt true\, which means that the room is lit (no light source is
  1521. needed while in the room).  You should create a \tt darkroom\
  1522. object rather than a \tt room\ with \tt islit\ set to \tt nil\ if you
  1523. want a dark room, because other methods are affected as well.
  1524. The \tt isseen\ property records whether the player has entered
  1525. the room before; initially it's \tt nil\, and is set to \tt true\
  1526. the first time the player enters.  The \tt roomAction( \it actor,
  1527. verb, directObject, preposition, indirectObject\ )\ method is
  1528. activated for each player command; by default, all it does is
  1529. call the room's location's \tt roomAction\ method if the room
  1530. is inside another room.  The \tt lookAround( \it verbosity\ )\
  1531. method displays the room's description for a given verbosity
  1532. level; \tt true\ means a full description, \tt nil\ means only
  1533. the short description (just the room name plus a list of the
  1534. objects present).  \tt roomDrop( \it object\ )\ is called when
  1535. an object is dropped within the room; normally, it just moves
  1536. the object to the room and displays ``Dropped.''  The \tt firstseen\
  1537. method is called when \tt isseen\ is about to be set \tt true\
  1538. for the first time (i.e., when the player first sees the room);
  1539. by default, this routine does nothing, but it's a convenient
  1540. place to put any special code you want to execute when a room
  1541. is first entered.  The \tt firstseen\ method is called \it after\
  1542. the room's description is displayed.
  1543. */
  1544.  
  1545. /*
  1546.  *  room: thing
  1547.  *
  1548.  *  A location in the game.  By default, the islit property is
  1549.  *  true, which means that the room is lit (no light source is
  1550.  *  needed while in the room).  You should create a darkroom
  1551.  *  object rather than a room with islit set to nil if you
  1552.  *  want a dark room, because other methods are affected as well.
  1553.  *  The isseen property records whether the player has entered
  1554.  *  the room before; initially it's nil, and is set to true
  1555.  *  the first time the player enters.  The roomAction( actor,
  1556.  *  verb, directObject, preposition, indirectObject ) method is
  1557.  *  activated for each player command; by default, all it does is
  1558.  *  call the room's location's roomAction method if the room
  1559.  *  is inside another room.  The lookAround( verbosity )
  1560.  *  method displays the room's description for a given verbosity
  1561.  *  level; true means a full description, nil means only
  1562.  *  the short description (just the room name plus a list of the
  1563.  *  objects present).  roomDrop( object ) is called when
  1564.  *  an object is dropped within the room; normally, it just moves
  1565.  *  the object to the room and displays "Dropped."  The firstseen
  1566.  *  method is called when isseen is about to be set true
  1567.  *  for the first time (i.e., when the player first sees the room);
  1568.  *  by default, this routine does nothing, but it's a convenient
  1569.  *  place to put any special code you want to execute when a room
  1570.  *  is first entered.  The firstseen method is called after
  1571.  *  the room's description is displayed.
  1572. */
  1573. room: thing
  1574.     topline = true    // DMB -- see nestedroom
  1575.     
  1576.     /*
  1577.      *   'reachable' is the list of explicitly reachable objects, over and
  1578.      *   above the objects that are here.  This is mostly used in nested
  1579.      *   rooms to make objects in the containing room accessible.  Most
  1580.      *   normal rooms will leave this as an empty list.
  1581.      */
  1582.     reachable = []
  1583.     
  1584.     /*
  1585.      *   roomCheck is true if the verb is valid in the room.  This
  1586.      *   is a first pass; generally, its only function is to disallow
  1587.      *   certain commands in a dark room.
  1588.      */
  1589.     roomCheck( v ) = { return( true ); }
  1590.     islit = true            // rooms are lit unless otherwise specified
  1591.     isseen = nil            // room has not been seen yet
  1592.     enterRoom( actor ) =    // sent to room as actor is entering it
  1593.     {
  1594.         self.lookAround(( not self.isseen ) or global.verbose );
  1595.         if ( self.islit )
  1596.     {
  1597.         if (not self.isseen) self.firstseen;
  1598.         self.isseen := true;
  1599.     }
  1600.     }
  1601.     roomAction( a, v, d, p, i ) =
  1602.     {
  1603.         if ( self.location ) self.location.roomAction( a, v, d, p, i );
  1604.     }
  1605.  
  1606.     /*
  1607.      *   Whenever a normal object (i.e., one that does not override the
  1608.      *   default doDrop provided by 'thing') is dropped, the actor's
  1609.      *   location is sent roomDrop(object being dropped).  By default, 
  1610.      *   we move the object into this room.
  1611.      */
  1612.     roomDrop( obj ) =
  1613.     {
  1614.         "Dropped. ";
  1615.     obj.moveInto( self );
  1616.     }
  1617.  
  1618.     /*
  1619.      *   Whenever an actor leaves this room, we run through the leaveList.
  1620.      *   This is a list of objects that have registered themselves with us
  1621.      *   via addLeaveList().  For each object in the leaveList, we send
  1622.      *   a "leaving" message, with the actor as the parameter.  It should
  1623.      *   return true if it wants to be removed from the leaveList, nil
  1624.      *   if it wants to stay.
  1625.      */
  1626.     leaveList = []
  1627.     addLeaveList( obj ) =
  1628.     {
  1629.         self.leaveList := self.leaveList + obj;
  1630.     }
  1631.     leaveRoom( actor ) =
  1632.     {
  1633.         local tmplist, thisobj, i, tot;
  1634.  
  1635.         tmplist := self.leaveList;
  1636.     tot := length( tmplist );
  1637.     i := 1;
  1638.         while ( i <= tot )
  1639.         {
  1640.         thisobj := tmplist[i];
  1641.             if ( thisobj.leaving( actor ))
  1642.                 self.leaveList := self.leaveList - thisobj;
  1643.             i := i + 1;
  1644.         }
  1645.     }
  1646.     /*
  1647.      *   lookAround describes the room.  If verbosity is true, the full
  1648.      *   description is given, otherwise an abbreviated description (without
  1649.      *   the room's ldesc) is displayed.
  1650.      */
  1651.     nrmLkAround( verbosity ) =      // lookAround without location status
  1652.     {
  1653.         local l, cur, i, tot;
  1654.  
  1655.         if ( verbosity )
  1656.         {
  1657.             /* "\n\t"; self.ldesc; */
  1658.         "\b"; self.ldesc;    /* DMB */
  1659.  
  1660.             l := self.contents;
  1661.         tot := length( l );
  1662.         i := 1;
  1663.             while ( i <= tot )
  1664.             {
  1665.             cur := l[i];
  1666.                 if ( cur.isfixed ) cur.heredesc;
  1667.                 i := i + 1;
  1668.             }
  1669.         }
  1670.         /* "\n\t"; */
  1671.         if (itemcnt( self.contents ))
  1672.         {
  1673.             P(); I();    /* DMB */
  1674.             "You see "; listcont( self ); " here. ";
  1675.        }
  1676.         else {
  1677.             "\n\t";
  1678.         }
  1679.  
  1680.     /*
  1681.      * DMB add stuff to listcontcont so we can see if there's
  1682.          * anything to print before putting the paragraph separator out.
  1683.          */
  1684.     if (listcontcont(self, nil)) {
  1685.         P(); I();
  1686.         listcontcont(self, true);
  1687.     }
  1688.  
  1689.     /*
  1690.      * DMB: Hack for Colossal Cave: since the bear has a location
  1691.      * that's a method, his actorDesc doesn't get printed by
  1692.          * the code below.
  1693.          */
  1694.     if (Bear.isIn(self))
  1695.         Bear.actorDesc;
  1696.  
  1697.         l := self.contents;
  1698.     tot := length( l );
  1699.     i := 1;
  1700.         while ( i <= tot )
  1701.         {
  1702.         cur := l[i];
  1703.             if ( cur.isactor )
  1704.             {
  1705.                 if ( cur <> Me )
  1706.                 {
  1707.                     "\n\t";
  1708.                     cur.actorDesc;
  1709.                 }
  1710.             }
  1711.             i := i + 1;
  1712.         }
  1713.     }
  1714.     /* DMB: */
  1715.     statusline = { self.sdesc; }
  1716.     statusLine =
  1717.     {
  1718.         self.statusline;
  1719.     }
  1720.     lookAround( verbosity ) =
  1721.     {
  1722.         self.statusline; // DMB -- removed "\b";
  1723.         self.nrmLkAround( verbosity );
  1724.     }
  1725.     
  1726.     /*
  1727.      *   Direction handlers.  The directions are all set up to
  1728.      *   the default, which is no travel allowed.  To make travel
  1729.      *   possible in a direction, just assign a room to the direction
  1730.      *   property.
  1731.      */
  1732.     north = { return( self.noexit ); }
  1733.     south = { return( self.noexit ); }
  1734.     east  = { return( self.noexit ); }
  1735.     west  = { return( self.noexit ); }
  1736.     up    = { return( self.noexit ); }
  1737.     down  = { return( self.noexit ); }
  1738.     ne    = { return( self.noexit ); }
  1739.     nw    = { return( self.noexit ); }
  1740.     se    = { return( self.noexit ); }
  1741.     sw    = { return( self.noexit ); }
  1742.     in    = { return( self.noexit ); }
  1743.     out   = { return( self.noexit ); }
  1744.     
  1745.     /*
  1746.      *   noexit displays a message when the player attempts to travel
  1747.      *   in a direction in which travel is not possible.
  1748.      */
  1749.     noexit = { "%You% can't go that way. "; return( nil ); }
  1750. ;
  1751.  
  1752. /*
  1753. @darkroom: room
  1754. A dark room.  The player must have some object that can act as a
  1755. light source in order to move about and perform most operations
  1756. while in this room.  Note that the room's lights can be turned
  1757. on by setting the room's \tt lightsOn\ property to \tt true\;
  1758. do this instead of setting \tt islit\, because \tt islit\ is
  1759. a method which checks for the presence of a light source.
  1760. */
  1761. class darkroom: room        // An enterable area which might be dark
  1762.     islit =                 // true ONLY if something is lighting the room
  1763.     {
  1764.         local rem, cur, tot, i;
  1765.  
  1766.     if ( self.lightsOn ) return( true );
  1767.  
  1768.     rem := global.lamplist;
  1769.     tot := length( rem );
  1770.     i := 1;
  1771.     while ( i <= tot )
  1772.     {
  1773.         cur := rem[i];
  1774.         if ( cur.isIn( self ) and cur.islit ) return( true );
  1775.         i := i + 1;
  1776.     }
  1777.     return( nil );
  1778.     }
  1779.     roomAction( actor, v, dobj, prep, io ) =
  1780.     {
  1781.         if ( not self.islit and not v.isTravelVerb and not v.issysverb )
  1782.     {
  1783.         "%You% can't see a thing. ";
  1784.         exit;
  1785.     }
  1786.     else pass roomAction;
  1787.     }
  1788.     statusLine =
  1789.     {
  1790.         if ( self.islit ) pass statusLine;
  1791.     else "In the dark.";
  1792.     }
  1793.     lookAround( verbosity ) =
  1794.     {
  1795.         // DMB: Changed pitch dark message
  1796.         if ( self.islit ) pass lookAround;
  1797.     else "It is now pitch dark.
  1798.     If you proceed you will likely fall into a pit."; 
  1799.  
  1800.     }
  1801.     noexit =
  1802.     {
  1803.         if ( self.islit ) pass noexit;
  1804.     else
  1805.     {
  1806.         darkTravel();
  1807.         return( nil );
  1808.     }
  1809.     }
  1810.     roomCheck( v ) =
  1811.     {
  1812.         if ( self.islit or v.issysverb or v.isTravelVerb ) return( true );
  1813.     else
  1814.     {
  1815.         "It's pitch black.\n";
  1816.         return( nil );
  1817.     }
  1818.     }
  1819. ;
  1820.  
  1821. /*
  1822.  *  theFloor is a special item that appears in every room (hence
  1823.  *  the non-standard location property).  This object is included
  1824.  *  mostly for completeness, so that the player can refer to the
  1825.  *  floor; otherwise, it doesn't do much.  Dropping an item on the
  1826.  *  floor, for example, moves it to the current room.
  1827.  */
  1828. class theFloor: beditem
  1829.     onroom = true    // DMB so it won't say "in the ground"
  1830.     noun = 'floor' 'ground'
  1831.     sdesc = "ground"
  1832.     adesc = "the ground"
  1833.     location =
  1834.     {
  1835.         if ( Me.location = self )
  1836.             return( self.sitloc );
  1837.         else
  1838.             return( Me.location );
  1839.     }
  1840.     locationOK = true        // suppress warning about location being a method
  1841.     doSiton( actor ) =
  1842.     {
  1843.         "Okay, %you're% now sitting on "; self.thedesc; ". ";
  1844.         self.sitloc := actor.location;
  1845.         actor.moveInto( self );
  1846.     }
  1847.     doLieon( actor ) =
  1848.     {
  1849.     // DMB changed so it says "lying."
  1850.         "Okay, %you're% now lying on "; self.thedesc; ". ";
  1851.         self.sitloc := actor.location;
  1852.         actor.moveInto( self );
  1853.     }
  1854.     ioPutOn( actor, dobj ) =
  1855.     {
  1856.         dobj.doDrop( actor );
  1857.     }
  1858.     ioPutIn( actor, dobj ) =
  1859.     {
  1860.         dobj.doDrop( actor );
  1861.     }
  1862. ;
  1863.  
  1864. /*
  1865. @Actor: fixeditem, movableActor
  1866. A character in the game.  The \tt maxweight\ property specifies
  1867. the maximum weight that the character can carry, and the \tt maxbulk\
  1868. property specifies the maximum bulk the character can carry.  The
  1869. \tt actorAction( \it verb, directObject, preposition, indirectObject\ )\
  1870. method specifies what happens when the actor is given a command by
  1871. the player; by default, the actor ignores the command and displays
  1872. a message to this effect.  The \tt isCarrying( \it object\ )\
  1873. method returns \tt true\ if the \it object\ is being carried by
  1874. the actor.  The \tt actorDesc\ method displays a message when the
  1875. actor is in the current room; this message is displayed along with
  1876. a room's description when the room is entered or examined.  The
  1877. \tt verGrab( \it object\ )\ method is called when someone tries to
  1878. take an object the actor is carrying; by default, an actor won't
  1879. let other characters take its possessions.
  1880.  
  1881. If you want the player to be able to follow the actor when it
  1882. leaves the room, you should define a \tt follower\ object to shadow
  1883. the character, and set the actor's \tt myfollower\ property to
  1884. the \tt follower\ object.  The \tt follower\ is then automatically
  1885. moved around just behind the actor by the actor's \tt moveInto\
  1886. method.
  1887.  
  1888. The \tt isHim\ property should return \tt true\ if the actor can
  1889. be referred to by the player as ``him,'' and likewise \tt isHer\
  1890. should be set to \tt true\ if the actor can be referred to as ``her.''
  1891. Note that both or neither can be set; if neither is set, the actor
  1892. can only be referred to as ``it,'' and if both are set, any of ``him,''
  1893. ``her,'' or ``it'' will be accepted.
  1894. */
  1895. class Actor: fixeditem, movableActor
  1896. ;
  1897.  
  1898. /*
  1899. @movableActor: qcontainer
  1900. Just like an \tt Actor\ object, except that the player can
  1901. manipulate the actor like an ordinary item.  Useful for certain
  1902. types of actors, such as small animals.
  1903. */
  1904. class movableActor: qcontainer // A character in the game
  1905.     isListed = nil          // described separately from room's contents
  1906.     weight = 10             // actors are pretty heavy
  1907.     bulk = 10               // and pretty bulky
  1908.     maxweight = 50          // Weight that can be carried at once
  1909.     maxbulk = 20            // Number of objects that can be carried at once
  1910.     isactor = true          // flag that this is an actor
  1911.     actorAction( v, d, p, i ) =
  1912.     {
  1913.         caps(); self.thedesc; " doesn't appear interested. ";
  1914.         exit;
  1915.     }
  1916.     isCarrying( obj ) = { return( obj.isIn( self )); }
  1917.     actorDesc =
  1918.     {
  1919.         caps(); self.adesc; " is here. ";
  1920.     }
  1921.     verGrab( item ) =
  1922.     {
  1923.         caps(); self.thedesc; " is carrying "; item.thedesc;
  1924.         " and won't let %youm% have it. ";
  1925.     }
  1926.     verDoFollow( actor ) =
  1927.     {
  1928.         "But "; self.thedesc; " is right here! ";
  1929.     }
  1930.     moveInto( obj ) =
  1931.     {
  1932.         if ( self.myfollower ) self.myfollower.moveInto( self.location );
  1933.     pass moveInto;
  1934.     }
  1935.     // these properties are for the format strings
  1936.     fmtYou = "he"
  1937.     fmtYour = "his"
  1938.     fmtYoure = "he's"
  1939.     fmtYoum = "him"
  1940.     fmtYouve = "he's"
  1941.     fmtS = "s"
  1942.     fmtEs = "es"
  1943.     fmtHave = "has"
  1944.     fmtDo = "does"
  1945.     fmtAre = "is"
  1946. ;
  1947.  
  1948. /*
  1949. @follower: Actor
  1950. This is a special object that can ``shadow'' the movements of a
  1951. character as it moves from room to room.  The purpose of a \tt follower\
  1952. is to allow the player to follow an actor as it leaves a room by
  1953. typing a ``follow'' command.  Each actor that is to be followed must
  1954. have its own \tt follower\ object.  The \tt follower\ object should
  1955. define all of the same vocabulary words (nouns and adjectives) as the
  1956. actual actor to which it refers.  The \tt follower\ must also
  1957. define the \tt myactor\ property to be the \tt Actor\ object that
  1958. the \tt follower\ follows.  The \tt follower\ will always stay
  1959. one room behind the character it follows; no commands are effective
  1960. with a \tt follower\ except for ``follow.''
  1961. */
  1962. class follower: Actor
  1963.     sdesc = { self.myactor.sdesc; }
  1964.     isfollower = true
  1965.     ldesc = { caps(); self.thedesc; " is no longer here. "; }
  1966.     actorAction( v, d, p, i ) = { self.ldesc; }
  1967.     actorDesc = {}
  1968.     myactor = nil   // set to the Actor to be followed
  1969.     verDoFollow( actor ) = {}
  1970.     doFollow( actor ) =
  1971.     {
  1972.         actor.travelTo( self.myactor.location );
  1973.     }
  1974. ;
  1975.  
  1976. /*
  1977. @basicMe: Actor
  1978. A default implementation of the \tt Me\ object, which is the
  1979. player character.  \tt adv.t\ defines \tt basicMe\ instead of
  1980. \tt Me\ to allow your game to override parts of the default
  1981. implementation while still using the rest, and without changing
  1982. \tt adv.t\ itself.  To use \tt basicMe\ unchanged as your player
  1983. character, include this in your game:  ``\tt Me: basicMe;\''.
  1984.  
  1985. The \tt basicMe\ object defines all of the methods and properties
  1986. required for an actor, with appropriate values for the player
  1987. character.  The nouns ``me'' and ``myself'' are defined (``I''
  1988. is not defined, because it conflicts with the ``inventory''
  1989. command's minimal abbreviation of ``i'' in certain circumstances,
  1990. and is generally not compatible with the syntax of most player
  1991. commands anyway).  The \tt sdesc\ is ``you''; the \tt thedesc\
  1992. and \tt adesc\ are ``yourself,'' which is appropriate for most
  1993. contexts.  The \tt maxbulk\ and \tt maxweight\ properties are
  1994. set to 10 each; a more sophisticated \tt Me\ might include the
  1995. player's state of health in determining the \tt maxweight\ and
  1996. \tt maxbulk\ properties.
  1997. */
  1998. class basicMe: Actor
  1999.     roomCheck( v ) = { return( self.location.roomCheck( v )); }
  2000.     noun = 'me' 'myself'
  2001.     sdesc = "you"
  2002.     thedesc = "yourself"
  2003.     adesc = "yourself"
  2004.     ldesc = "You look about the same as always. "
  2005.     maxweight = 10
  2006.     maxbulk = 10
  2007.     verDoFollow( actor ) =
  2008.     {
  2009.         if ( actor = self ) "You can't follow yourself! ";
  2010.     }
  2011.     actorAction( verb, dobj, prep, iobj ) = 
  2012.     {
  2013.     }
  2014.     travelTo( room ) =
  2015.     {
  2016.         if ( room )
  2017.         {
  2018.         if ( room.isobstacle )
  2019.         {
  2020.             self.travelTo( room.destination );
  2021.         }
  2022.         else if ( not ( self.location.islit or room.islit ))
  2023.         {
  2024.             darkTravel();
  2025.         }
  2026.         else
  2027.         {
  2028.                 if ( self.location ) self.location.leaveRoom( self );
  2029.                 self.location := room;
  2030.                 room.enterRoom( self );
  2031.         }
  2032.         }
  2033.     }
  2034.     moveInto( room ) =
  2035.     {
  2036.         self.location := room;
  2037.     }
  2038.     // these properties are for the format strings
  2039.     fmtYou = "you"
  2040.     fmtYour = "your"
  2041.     fmtYoure = "you're"
  2042.     fmtYoum = "you"
  2043.     fmtYouve = "you've"
  2044.     fmtS = ""
  2045.     fmtEs = ""
  2046.     fmtHave = "have"
  2047.     fmtDo = "do"
  2048.     fmtAre = "are"
  2049. ;
  2050.  
  2051. /*
  2052. @decoration: fixeditem
  2053. An item that doesn't have any function in the game, apart from
  2054. having been mentioned in the room description.  These items
  2055. are immovable and can't be manipulated in any way, but can be
  2056. referred to and inspected.  Liberal use of \tt decoration\ items
  2057. can improve a game's playability by helping the parser recognize
  2058. all the words the game uses in its descriptions of rooms.
  2059. */
  2060. class decoration: fixeditem
  2061. ;
  2062.  
  2063. /*
  2064. @buttonitem: fixeditem
  2065. A button (the type you push).  The individual button's method
  2066. \tt doPush( \it actor\ )\, which must be specified in
  2067. the button, carries out the function of the button.  Note that
  2068. all buttons have the noun ``button'' defined.
  2069. */
  2070. class buttonitem: fixeditem
  2071.     noun = 'button'
  2072.     plural = 'buttons'
  2073.     verDoPush( actor ) = {}
  2074. ;
  2075.  
  2076. /*
  2077. @clothingItem: item
  2078. Something that can be worn.  By default, the only thing that
  2079. happens when the item is worn is that its \tt isworn\ property
  2080. is set to \tt true\.  If you want more to happen, override the
  2081. \tt doWear( \it actor\ )\ property.  Note that, when a \tt clothingItem\
  2082. is being worn, certain operations will cause it to be removed (for
  2083. example, dropping it causes it to be removed).  If you want
  2084. something else to happen, override the \tt checkDrop\ method;
  2085. if you want to disallow such actions while the object is worn,
  2086. use an \tt exit\ statement in the \tt checkDrop\ method.
  2087. */
  2088. class clothingItem: item
  2089.     checkDrop =
  2090.     {
  2091.         if ( self.isworn )
  2092.     {
  2093.         "(Taking off "; self.thedesc; " first)\n";
  2094.     }
  2095.     }
  2096.     doDrop( actor ) =
  2097.     {
  2098.         self.checkDrop;
  2099.     pass doDrop;
  2100.     }
  2101.     doPutIn( actor, io ) =
  2102.     {
  2103.         self.checkDrop;
  2104.     pass doPutIn;
  2105.     }
  2106.     doPutOn( actor, io ) =
  2107.     {
  2108.         self.checkDrop;
  2109.     pass doPutOn;
  2110.     }
  2111.     doGiveTo( actor, io ) =
  2112.     {
  2113.         self.checkDrop;
  2114.     pass doGiveTo;
  2115.     }
  2116.     doThrowAt( actor, io ) =
  2117.     {
  2118.         self.checkDrop;
  2119.     pass doThrowAt;
  2120.     }
  2121.     doThrowTo( actor, io ) =
  2122.     {
  2123.         self.checkDrop;
  2124.     pass doThrowTo;
  2125.     }
  2126.     doThrow( actor ) =
  2127.     {
  2128.         self.checkDrop;
  2129.     pass doThrow;
  2130.     }
  2131.     moveInto( obj ) =
  2132.     {
  2133.         /*
  2134.      *   Catch any other movements with moveInto; this won't stop the
  2135.      *   movement from happening, but it will prevent any anamolous
  2136.      *   consequences caused by the object moving but still being worn.
  2137.      */
  2138.         self.isworn := nil;
  2139.     pass moveInto;
  2140.     }
  2141.     verDoWear( actor ) =
  2142.     {
  2143.         if ( self.isworn )
  2144.         {
  2145.             "%You're% already wearing "; self.thedesc; "! ";
  2146.         }
  2147.         else if ( not actor.isCarrying( self ))
  2148.         {
  2149.             "%You% %do%n't have "; self.thedesc; ". ";
  2150.         }
  2151.     }
  2152.     doWear( actor ) =
  2153.     {
  2154.         "Okay, %you're% now wearing "; self.thedesc; ". ";
  2155.         self.isworn := true;
  2156.     }
  2157.     verDoUnwear( actor ) =
  2158.     {
  2159.         if ( not self.isworn )
  2160.         {
  2161.             "%You're% not wearing "; self.thedesc; ". ";
  2162.         }
  2163.     }
  2164.     doUnwear( actor ) =
  2165.     {
  2166.         "Okay, %you're% no longer wearing "; self.thedesc; ". ";
  2167.         self.isworn := nil;
  2168.     }
  2169. ;
  2170.  
  2171. /*
  2172. @obstacle: object
  2173. An \tt obstacle\ is used in place of a room for a direction
  2174. property.  The \tt destination\ property specifies the room that
  2175. is reached if the obstacle is successfully negotiated; when the
  2176. obstacle is not successfully negotiated, \tt destination\ should
  2177. display an appropriate message and return \tt nil\.
  2178. */
  2179. class obstacle: object
  2180.     isobstacle = true
  2181. ;
  2182.  
  2183. /*
  2184. @doorway: fixeditem, obstacle
  2185. A \tt doorway\ is an obstacle that impedes progress when it is closed.
  2186. When the door is open (\tt isopen\ is \tt true\), the user ends up in
  2187. the room specified in the \tt doordest\ property upon going through
  2188. the door.  Since a doorway is an obstacle, use the door object for
  2189. a direction property of the room containing the door.
  2190.  
  2191. If \tt noAutoOpen\ is not set to \tt true\, the door will automatically
  2192. be opened when the player tries to walk through the door, unless the
  2193. door is locked (\tt islocked\ = \tt true\).  If the door is locked,
  2194. it can be unlocked simply by typing ``unlock door'', unless the
  2195. \tt mykey\ property is set, in which case the object specified in
  2196. \tt mykey\ must be used to unlock the door.  Note that the door can
  2197. only be relocked by the player under the circumstances that allow
  2198. unlocking, plus the property \tt islockable\ must be set true.
  2199. By default, the door is closed; set \tt isopen\ to true if the door
  2200. is to start out open (and be sure to open the other side as well).
  2201.  
  2202. \tt otherside\ specifies the corresponding doorway object in the
  2203. destination room (\tt doordest\), if any.  If \tt otherside\ is
  2204. specified, its \tt isopen\ and \tt islocked\ properties will be
  2205. kept in sync automatically.
  2206. */
  2207. class doorway: fixeditem, obstacle
  2208.     isdoor = true           // Item can be opened and closed
  2209.     destination =
  2210.     {
  2211.         if ( self.isopen ) return( self.doordest );
  2212.     else if ( not self.islocked and not self.noAutoOpen )
  2213.     {
  2214.         self.isopen := true;
  2215.         if ( self.otherside ) self.otherside.isopen := true;
  2216.         "(Opening << self.thedesc >>)\n";
  2217.         return( self.doordest );
  2218.     }
  2219.     else
  2220.     {
  2221.         "%You%'ll have to open << self.thedesc >> first. ";
  2222.         setit( self );
  2223.         return( nil );
  2224.     }
  2225.     }
  2226.     verDoOpen( actor ) =
  2227.     {
  2228.         if ( self.isopen ) "It's already open. ";
  2229.     else if ( self.islocked ) "It's locked. ";
  2230.     }
  2231.     doOpen( actor ) =
  2232.     {
  2233.         "Opened. ";
  2234.     self.isopen := true;
  2235.     if ( self.otherside ) self.otherside.isopen := true;
  2236.     }
  2237.     verDoClose( actor ) =
  2238.     {
  2239.         if ( not self.isopen ) "It's already closed. ";
  2240.     }
  2241.     doClose( actor ) =
  2242.     {
  2243.         "Closed. ";
  2244.     self.isopen := nil;
  2245.     if ( self.otherside ) self.otherside.isopen := nil;
  2246.     }
  2247.     verDoLock( actor ) =
  2248.     {
  2249.         if ( self.islocked ) "It's already locked! ";
  2250.     else if ( not self.islockable ) "It can't be locked. ";
  2251.     else if ( self.isopen ) "%You%'ll have to close it first. ";
  2252.     }
  2253.     doLock( actor ) =
  2254.     {
  2255.         if ( self.mykey = nil )
  2256.     {
  2257.         "Locked. ";
  2258.         self.islocked := true;
  2259.         if ( self.otherside ) self.otherside.islocked := true;
  2260.     }
  2261.     else
  2262.             askio( withPrep );
  2263.     }
  2264.     verDoUnlock( actor ) =
  2265.     {
  2266.         if ( not self.islocked ) "It's not locked! ";
  2267.     }
  2268.     doUnlock( actor ) =
  2269.     {
  2270.         if ( self.mykey = nil )
  2271.     {
  2272.         "Unlocked. ";
  2273.         self.islocked := nil;
  2274.         if ( self.otherside ) self.otherside.islocked := nil;
  2275.     }
  2276.     else
  2277.         askio( withPrep );
  2278.     }
  2279.     verDoLockWith( actor, io ) =
  2280.     {
  2281.         if ( self.islocked ) "It's already locked. ";
  2282.     else if ( not self.islockable ) "It can't be locked. ";
  2283.     else if ( self.mykey = nil )
  2284.         "%You% %do%n't need anything to lock it. ";
  2285.     else if ( self.isopen ) "%You%'ll have to close it first. ";
  2286.     }
  2287.     doLockWith( actor, io ) =
  2288.     {
  2289.         if ( io = self.mykey )
  2290.     {
  2291.         "Locked. ";
  2292.         self.islocked := true;
  2293.         if ( self.otherside ) self.otherside.islocked := true;
  2294.     }
  2295.     else "It doesn't fit the lock. ";
  2296.     }
  2297.     verDoUnlockWith( actor, io ) =
  2298.     {
  2299.         if ( not self.islocked ) "It's not locked! ";
  2300.     else if ( self.mykey = nil )
  2301.         "%You% %do%n't need anything to unlock it. ";
  2302.     }
  2303.     doUnlockWith( actor, io ) =
  2304.     {
  2305.         if ( io = self.mykey )
  2306.     {
  2307.         "Unlocked. ";
  2308.         self.islocked := nil;
  2309.         if ( self.otherside ) self.otherside.islocked := nil;
  2310.     }
  2311.     else "It doesn't fit the lock. ";
  2312.     }
  2313.     ldesc =
  2314.     {
  2315.     if ( self.isopen ) "It's open. ";
  2316.     else
  2317.     {
  2318.         if ( self.islocked ) "It's closed and locked. ";
  2319.         else "It's closed. ";
  2320.     }
  2321.     }
  2322. ;
  2323.  
  2324. /*
  2325. @lockableDoorway: doorway
  2326. This is just a normal doorway with the \tt islockable\ and
  2327. \tt islocked\ properties set to \tt true\.  Fill in the other
  2328. properties (\tt otherside\ and \tt doordest\) as usual.  If
  2329. the door has a key, set property \tt mykey\ to the key object.
  2330. */
  2331. class lockableDoorway: doorway
  2332.     islockable = true
  2333.     islocked = true
  2334. ;
  2335.  
  2336. /*
  2337. @vehicle: item, nestedroom
  2338. This is an object that an actor can board.  An actor cannot go
  2339. anywhere while on board a vehicle; the actor must get out first.
  2340. */
  2341. class vehicle: item, nestedroom
  2342.     reachable = ([] + self)
  2343.     isvehicle = true
  2344.     verDoEnter( actor ) = { self.verDoBoard( actor ); }
  2345.     doEnter( actor ) = { self.doBoard( actor ); }
  2346.     verDoBoard( actor ) =
  2347.     {
  2348.         if ( actor.location = self )
  2349.         {
  2350.             "%You're% already in "; self.thedesc; "! ";
  2351.         }
  2352.     }
  2353.     doBoard( actor ) =
  2354.     {
  2355.         "Okay, %you're% now in "; self.thedesc; ". ";
  2356.         actor.moveInto( self );
  2357.     }
  2358.     noexit =
  2359.     {
  2360.         "%You're% not going anywhere until %you% get%s% out of ";
  2361.       self.thedesc; ". ";
  2362.         return( nil );
  2363.     }
  2364.     out = ( self.location )
  2365. ;
  2366.  
  2367. /*
  2368. @surface: item
  2369. Objects can be placed on a surface.  Apart from using the
  2370. preposition ``on'' rather than ``in'' to refer to objects
  2371. contained by the object, a \tt surface\ is identical to a
  2372. \tt container\.  Note: that an object cannot be both a
  2373. \tt surface\ and a \tt container\, because there is no
  2374. distinction between the two internally.
  2375. */
  2376. class surface: item
  2377.     issurface = true        // Item can hold objects on its surface
  2378.     ldesc =
  2379.     {
  2380.         if (itemcnt( self.contents ))
  2381.         {
  2382.             "On "; self.thedesc; " %you% see%s% "; listcont( self ); ". ";
  2383.         }
  2384.         else
  2385.         {
  2386.             "There's nothing on "; self.thedesc; ". ";
  2387.         }
  2388.     }
  2389.     verIoPutOn( actor ) = {}
  2390.     ioPutOn( actor, dobj ) =
  2391.     {
  2392.         dobj.doPutOn( actor, self );
  2393.     }
  2394. ;
  2395.  
  2396. /*
  2397. @container: item
  2398. This object can contain other objects.  The \tt iscontainer\ property
  2399. is set to \tt true\.  The default \tt ldesc\ displays a list of the
  2400. objects inside the container, if any.  The \tt maxbulk\ property
  2401. specifies the maximum amount of bulk the container can contain.
  2402. */
  2403. class container: item
  2404.     maxbulk = 10            // maximum bulk the container can contain
  2405.     isopen = true           // in fact, it can't be closed at all
  2406.     iscontainer = true      // Item can contain other items
  2407.     ldesc =
  2408.     {
  2409.         if ( self.contentsVisible and itemcnt( self.contents ) <> 0 )
  2410.         {
  2411.             "In "; self.thedesc; " %you% see%s% "; listcont( self ); ". ";
  2412.         }
  2413.         else
  2414.         {
  2415.             "There's nothing in "; self.thedesc; ". ";
  2416.         }
  2417.     }
  2418.     verIoPutIn( actor ) =
  2419.     {
  2420.     }
  2421.     ioPutIn( actor, dobj ) =
  2422.     {
  2423.         if (addbulk( self.contents ) + dobj.bulk > self.maxbulk )
  2424.         {
  2425.             "%You% can't fit that in "; self.thedesc; ". ";
  2426.         }
  2427.         else
  2428.         {
  2429.         dobj.doPutIn( actor, self );
  2430.         }
  2431.     }
  2432.     verDoLookin( actor ) = {}
  2433.     doLookin( actor ) =
  2434.     {
  2435.         self.ldesc;
  2436.     }
  2437. ;
  2438.  
  2439. /*
  2440. @openable: container
  2441. A container that can be opened and closed.  The \tt isopenable\
  2442. property is set to \tt true\.  The default \tt ldesc\ displays
  2443. the contents of the container if the container is open, otherwise
  2444. a message saying that the object is closed.
  2445. */
  2446. class openable: container
  2447.     contentsReachable = { return( self.isopen ); }
  2448.     contentsVisible = { return( self.isopen ); }
  2449.     isopenable = true
  2450.     ldesc =
  2451.     {
  2452.         caps(); self.thedesc;
  2453.         if ( self.isopen )
  2454.     {
  2455.         " is open. ";
  2456.         pass ldesc;
  2457.     }
  2458.         else " is closed. ";
  2459.     }
  2460.     isopen = true
  2461.     verDoOpen( actor ) =
  2462.     {
  2463.         if ( self.isopen )
  2464.     {
  2465.         caps(); self.thedesc; " is already open! ";
  2466.     }
  2467.     }
  2468.     doOpen( actor ) =
  2469.     {
  2470.         if (itemcnt( self.contents ))
  2471.     {
  2472.         "Opening "; self.thedesc; " reveals "; listcont( self ); ". ";
  2473.     }
  2474.     else "Opened. ";
  2475.     self.isopen := true;
  2476.     }
  2477.     verDoClose( actor ) =
  2478.     {
  2479.         if ( not self.isopen )
  2480.     {
  2481.         caps(); self.thedesc; " is already closed! ";
  2482.     }
  2483.     }
  2484.     doClose( actor ) =
  2485.     {
  2486.         "Closed. ";
  2487.     self.isopen := nil;
  2488.     }
  2489.     verIoPutIn( actor ) =
  2490.     {
  2491.         if ( not self.isopen )
  2492.     {
  2493.         caps(); self.thedesc; " is closed. ";
  2494.     }
  2495.     }
  2496.     verDoLookin( actor ) =
  2497.     {
  2498.         if ( not self.isopen ) "It's closed. ";
  2499.     }
  2500. ;
  2501.  
  2502. /*
  2503. @qcontainer: container
  2504. A ``quiet'' container:  its contents are not listed when it shows
  2505. up in a room description or inventory list.  The \tt isqcontainer\
  2506. property is set to \tt true\.
  2507. */
  2508. class qcontainer: container
  2509.     isqcontainer = true
  2510. ;
  2511.  
  2512. /*
  2513. @lockable: openable
  2514. A container that can be locked and unlocked.  The \tt islocked\
  2515. property specifies whether the object can be opened or not.  The
  2516. object can be locked and unlocked without the need for any other
  2517. object; if you want a key to be involved, use a \tt keyedLockable\.
  2518. */
  2519. class lockable: openable
  2520.     doOpen( actor ) =
  2521.     {
  2522.         if ( self.islocked )
  2523.         {
  2524.             "It's locked. ";
  2525.         }
  2526.         else pass doOpen;
  2527.     }
  2528.     verDoLock( actor ) =
  2529.     {
  2530.         if ( self.islocked )
  2531.         {
  2532.             "It's already locked! ";
  2533.         }
  2534.     }
  2535.     doLock( actor ) =
  2536.     {
  2537.         if ( self.isopen )
  2538.         {
  2539.             "%You%'ll have to close "; self.thedesc; " first. ";
  2540.         }
  2541.         else
  2542.         {
  2543.             "Locked. ";
  2544.             self.islocked := true;
  2545.         }
  2546.     }
  2547.     verDoUnlock( actor ) =
  2548.     {
  2549.         if ( not self.islocked ) "It's not locked! ";
  2550.     }
  2551.     doUnlock( actor ) =
  2552.     {
  2553.         "Unlocked. ";
  2554.         self.islocked := nil;
  2555.     }
  2556.     verDoLockWith( actor, io ) =
  2557.     {
  2558.         if ( self.islocked ) "It's already locked. ";
  2559.     }
  2560.     verDoUnlockWith( actor, io ) =
  2561.     {
  2562.         if ( not self.islocked ) "It's not locked! ";
  2563.     }
  2564. ;
  2565.  
  2566. /*
  2567. @keyedLockable: lockable
  2568. This subclass of \tt lockable\ allows you to create an object
  2569. that can only be locked and unlocked with a corresponding key.
  2570. Set the property \tt mykey\ to the \tt keyItem\ object that can
  2571. lock and unlock the object.
  2572. */
  2573. class keyedLockable: lockable
  2574.     mykey = nil     // set 'mykey' to the key which locks/unlocks me
  2575.     doLock( actor ) =
  2576.     {
  2577.         askio( withPrep );
  2578.     }
  2579.     doUnlock( actor ) =
  2580.     {
  2581.         askio( withPrep );
  2582.     }
  2583.     doLockWith( actor, io ) =
  2584.     {
  2585.         if ( self.isopen )
  2586.         {
  2587.             "%You% can't lock << self.thedesc >> when it's open. ";
  2588.         }
  2589.         else if ( io = self.mykey )
  2590.         {
  2591.             "Locked. ";
  2592.             self.islocked := true;
  2593.         }
  2594.         else "It doesn't fit the lock. ";
  2595.     }
  2596.     doUnlockWith( actor, io ) =
  2597.     {
  2598.         if ( io = self.mykey )
  2599.         {
  2600.             "Unlocked. ";
  2601.             self.islocked := nil;
  2602.         }
  2603.         else "It doesn't fit the lock. ";
  2604.     }
  2605. ;
  2606.  
  2607. /*
  2608. @keyItem: item
  2609. This is an object that can be used as a key for a \tt keyedLockable\
  2610. or \tt lockableDoorway\ object.  It otherwise behaves as an ordinary item.
  2611. */
  2612. class keyItem: item
  2613.     verIoUnlockWith( actor ) = {}
  2614.     ioUnlockWith( actor, dobj ) =
  2615.     {
  2616.         dobj.doUnlockWith( actor, self );
  2617.     }
  2618.     verIoLockWith( actor ) = {}
  2619.     ioLockWith( actor, dobj ) =
  2620.     {
  2621.         dobj.doLockWith( actor, self );
  2622.     }
  2623. ;
  2624.  
  2625. /*
  2626. @transparentItem: item
  2627. An object whose contents are visible, even when the object is
  2628. closed.  Whether the contents are reachable is decided in the
  2629. normal fashion.  This class is useful for items such as glass
  2630. bottles, whose contents can be seen when the bottle is closed
  2631. but cannot be reached.
  2632. */
  2633. class transparentItem: item
  2634.     contentsVisible = { return( true ); }
  2635.     verGrab( obj ) =
  2636.     {
  2637.         if ( self.isopenable and not self.isopen )
  2638.             "%You% will have to open << self.thedesc >> first. ";
  2639.     }
  2640.     doOpen( actor ) =
  2641.     {
  2642.         self.isopen := true;
  2643.         "Opened. ";
  2644.     }
  2645. ;
  2646.  
  2647. /*
  2648. @basicNumObj: object
  2649. This object provides a default implementation for \tt numObj\.
  2650. To use this default unchanged in your game, include in your
  2651. game this line:  ``\tt numObj: basicNumObj\''.
  2652. */
  2653. class basicNumObj: object   // when a number is used in a player command,
  2654.     value = 0               //  this is set to its value
  2655.     sdesc = "that"
  2656.     adesc = "that"
  2657.     thedesc = "that"
  2658.     verDoTypeOn( actor, io ) = {}
  2659.     doTypeOn( actor, io ) = { "\"Tap, tap, tap, tap...\" "; }
  2660.     verIoTurnTo( actor ) = {}
  2661.     ioTurnTo( actor, dobj ) = { dobj.doTurnTo( actor, self ); }
  2662. ;
  2663.  
  2664. /*
  2665. @basicStrObj: object
  2666. This object provides a default implementation for \tt strObj\.
  2667. To use this default unchanged in your game, include in your
  2668. game this line:  ``\tt strObj: basicStrObj\''.
  2669. */
  2670. class basicStrObj: object   // when a string is used in a player command,
  2671.     value = ''              //  this is set to its value
  2672.     sdesc = "that"
  2673.     adesc = "that"
  2674.     thedesc = "that"
  2675.     verDoTypeOn( actor, io ) = {}
  2676.     doTypeOn( actor, io ) = { "\"Tap, tap, tap, tap...\" "; }
  2677.     verDoSave( actor ) = {}
  2678.     doSave( actor ) =
  2679.     {
  2680.         if (save( self.value ))
  2681.             "Save failed. ";
  2682.         else
  2683.             "Saved. ";
  2684.     abort;
  2685.     }
  2686.     verDoRestore( actor ) = {}
  2687.     doRestore( actor ) =
  2688.     {
  2689.         if (restore( self.value ))
  2690.             "Restore failed. ";
  2691.         else
  2692.     {
  2693.             "Restored. ";
  2694.         setscore( global.score, global.turnsofar );
  2695.     }
  2696.         abort;
  2697.     }
  2698.     verDoScript( actor ) = {}
  2699.     doScript( actor ) =
  2700.     {
  2701.         logging( self.value );
  2702.         "Writing script file. ";
  2703.         abort;
  2704.     }
  2705.     verDoSay( actor ) = {}
  2706.     doSay( actor ) =
  2707.     {
  2708.         // DMB added ZOT code, etc.
  2709.         if (upper(strObj.value) = 'XYZZY') {
  2710.             xyzzyVerb.action(actor);
  2711.         }
  2712.             else if (upper(strObj.value) = 'PLUGH') {
  2713.             plughVerb.action(actor);
  2714.         }
  2715.         else if (upper(strObj.value) = 'PLOVER') {
  2716.             ploverVerb.action(actor);
  2717.         }
  2718.            else if (upper(strObj.value) = 'Y2') {
  2719.             y2Verb.action(actor);
  2720.         }
  2721.            else if (upper(strObj.value) = 'FEE') {
  2722.             feeVerb.action(actor);
  2723.         }
  2724.            else if (upper(strObj.value) = 'FIE') {
  2725.             fieVerb.action(actor);
  2726.         }
  2727.            else if (upper(strObj.value) = 'FOE') {
  2728.             foeVerb.action(actor);
  2729.         }
  2730.            else if (upper(strObj.value) = 'FOO') {
  2731.             fooVerb.action(actor);
  2732.         }
  2733.            else if (upper(strObj.value) = 'FUM') {
  2734.             fumVerb.action(actor);
  2735.         }
  2736.         else if (upper(strObj.value) = 'FEE FIE FOE FOO') {
  2737.             "Try saying the words one at a time.";
  2738.         }
  2739.         else if (upper(strObj.value) = 'FEE FIE FOE FUM') {
  2740.             "Try saying the words one at a time.";
  2741.         }
  2742.         else {
  2743.             "That doesn't seem very productive.";
  2744.         }
  2745.     }
  2746. ;
  2747.  
  2748. /*
  2749. @deepverb: object
  2750. A ``verb object'' that is referenced by the parser when the player
  2751. uses an associated vocabulary word.  A \tt deepverb\ contains both
  2752. the vocabulary of the verb and a description of available syntax.
  2753. The \tt verb\ property lists the vocabulary words known as verbs;
  2754. one word (such as \tt 'take'\) or a pair (such as \tt 'pick up'\)
  2755. can be used.  In the latter case, the second word must be a
  2756. preposition, and may move to the end of the sentence in a player's
  2757. command, as in ``pick it up.''  The \tt action( \it actor\ )\
  2758. method specifies what happens when the verb is used without any
  2759. objects; its absence specifies that the verb cannot be used without
  2760. an object.  The \tt doAction\ specifies the root of the message
  2761. names (in single quotes) sent to the direct object when the verb
  2762. is used with a direct object; its absence means that a single object
  2763. is not allowed.  Likewise, the \tt ioAction( \it preposition\ )\
  2764. specifies the root of the message name sent to the direct and
  2765. indirect objects when the verb is used with both a direct and
  2766. indirect object; its absence means that this syntax is illegal.
  2767. Several \tt ioAction\ properties may be present:  one for each
  2768. preposition that can be used with an indirect object with the verb.
  2769.  
  2770. The \tt validDo( \it actor, object, seqno\ )\ method returns \tt true\
  2771. if the indicated object is valid as a direct object for this actor.
  2772. The \tt validIo( \it actor, object, seqno\ )\ method does likewise
  2773. for indirect objects.  The \it seqno\ parameter is a ``sequence
  2774. number,'' starting with 1 for the first object tried for a given
  2775. verb, 2 for the second, and so forth; this parameter is normally
  2776. ignored, but can be used for some special purposes.  For example,
  2777. \tt askVerb\ does not distinguish between objects matching vocabulary
  2778. words, and therefore accepts only the first from a set of ambiguous
  2779. objects.  These methods do not normally need to be changed; by
  2780. default, they return \tt true\ if the object is accessible to the
  2781. actor.
  2782.  
  2783. The \tt doDefault( \it actor, prep, indirectObject\ )\ and
  2784. \tt ioDefault( \it actor, prep\ )\ methods return a list of the
  2785. default direct and indirect objects, respectively.  These lists
  2786. are used for determining which objects are meant by ``all'' and which
  2787. should be used when the player command is missing an object.  These
  2788. normally return a list of all objects that are applicable to the
  2789. current command.
  2790. */
  2791. class deepverb: object                // A deep-structure verb.
  2792.     validDo( actor, obj, seqno ) =
  2793.     {
  2794.         return( obj.isReachable( actor ));
  2795.     }
  2796.     invalidObj( actor, obj, name ) =
  2797.     {
  2798.         if ( not obj.isVisible( actor ))
  2799.             "I don't see any << name >> here. ";
  2800.         else
  2801.             "%You% can't do that with << obj.thedesc >>. ";
  2802.     }
  2803.     validIo( actor, obj, seqno ) =
  2804.     {
  2805.         return( obj.isReachable( actor ));
  2806.     }
  2807.     doDefault( actor, prep, io ) =
  2808.     {
  2809.     /* DMB */
  2810.     //return( actor.contents + actor.location.contents );
  2811.     return nil;
  2812.     }
  2813.     ioDefault( actor, prep ) =
  2814.     {
  2815.         /* DMB */
  2816.     //return( actor.contents + actor.location.contents );
  2817.     return nil;
  2818.     }
  2819. ;
  2820.  
  2821. /*
  2822.  *   Various verbs.
  2823.  */
  2824. inspectVerb: deepverb
  2825.     verb = 'inspect' 'examine' 'look at' 'x' /* DMB: */ 'search' 'ex'
  2826.     sdesc = "inspect"
  2827.     doAction = 'Inspect'
  2828.     validDo( actor, obj, seqno ) =
  2829.     {
  2830.         return( obj.isVisible( actor ));
  2831.     }
  2832. ;
  2833. askVerb: deepverb
  2834.     verb = 'ask'
  2835.     sdesc = "ask"
  2836.     prepDefault = aboutPrep
  2837.     ioAction( aboutPrep ) = 'AskAbout'
  2838.     validIo( actor, obj, seqno ) = { return( seqno = 1 ); }
  2839. ;
  2840. tellVerb: deepverb
  2841.     verb = 'tell'
  2842.     sdesc = "tell"
  2843.     prepDefault = aboutPrep
  2844.     ioAction( aboutPrep ) = 'TellAbout'
  2845.     validIo( actor, obj, seqno ) = { return( seqno = 1 ); }
  2846. ;
  2847. followVerb: deepverb
  2848.     sdesc = "follow"
  2849.     verb = 'follow'
  2850.     doAction = 'Follow'
  2851. ;
  2852. /*
  2853.  * DMB -- now defined in ccr-verbs.t
  2854. digVerb: deepverb
  2855.     verb = 'dig' 'dig in'
  2856.     sdesc = "dig in"
  2857.     prepDefault = withPrep
  2858.     ioAction( withPrep ) = 'DigWith'
  2859. ;
  2860.  */
  2861. /*
  2862.  * DMB -- now defined in ccr-verbs.t
  2863.  *
  2864. jumpVerb: deepverb
  2865.     verb = 'jump' 'jump over' 'jump off'
  2866.     doAction = 'Jump'
  2867.     action(actor) = { "Wheeee!"; }
  2868. ;
  2869. */
  2870. pushVerb: deepverb
  2871.     verb = 'push' 'press'
  2872.     sdesc = "push"
  2873.     doAction = 'Push'
  2874. ;
  2875. attachVerb: deepverb
  2876.     verb = 'attach' 'connect'
  2877.     sdesc = "attach"
  2878.     prepDefault = toPrep
  2879.     ioAction( toPrep ) = 'AttachTo'
  2880. ;
  2881. wearVerb: deepverb
  2882.     verb = 'wear' 'put on'
  2883.     sdesc = "wear"
  2884.     doAction = 'Wear'
  2885. ;
  2886. dropVerb: deepverb
  2887.     verb = 'drop' 'put down' 'free' 'release'    // DMB: added last two
  2888.     sdesc = "drop"
  2889.     ioAction( onPrep ) = 'PutOn'
  2890.     doAction = 'Drop'
  2891.     doDefault( actor, prep, io ) =
  2892.     {
  2893.         return( actor.contents );
  2894.     }
  2895. ;
  2896. removeVerb: deepverb
  2897.     verb = 'take off'
  2898.     sdesc = "take off"
  2899.     doAction = 'Unwear'
  2900.     ioAction( fromPrep ) = 'RemoveFrom'
  2901. ;
  2902. openVerb: deepverb
  2903.     verb = 'open' 'pry'        // DMB added pry for "pry clam with trident"
  2904.     sdesc = "open"
  2905.     doAction = 'Open'
  2906.     ioAction(withPrep) = 'OpenWith'
  2907. ;
  2908. closeVerb: deepverb
  2909.     verb = 'close'
  2910.     sdesc = "close"
  2911.     doAction = 'Close'
  2912. ;
  2913. putVerb: deepverb
  2914.     verb = 'put' 'place' 'insert'    // DMB: added 'insert'
  2915.     sdesc = "put"
  2916.     prepDefault = inPrep
  2917.     ioAction( inPrep ) = 'PutIn'
  2918.     ioAction( onPrep ) = 'PutOn'
  2919.     doDefault( actor, prep, io ) =
  2920.     {
  2921.         return( takeVerb.doDefault( actor, prep, io ) + actor.contents );
  2922.     }
  2923. ;
  2924. takeVerb: deepverb                   // This object defines how to take things
  2925.     verb = 'take' 'pick up' 'get' 'remove'
  2926.     sdesc = "take"
  2927.     ioAction( offPrep ) = 'TakeOff'
  2928.     ioAction( outPrep ) = 'TakeOut'
  2929.     ioAction( fromPrep ) = 'TakeOut'
  2930.     ioAction( inPrep ) = 'TakeOut'
  2931.     ioAction( onPrep ) = 'TakeOff'
  2932.     doAction = 'Take'
  2933.     doDefault( actor, prep, io ) =
  2934.     {
  2935.         local ret, rem, cur, rem2, cur2, tot, i, tot2, j;
  2936.     
  2937.     ret := [];
  2938.         
  2939.     /*
  2940.      *   For "take all out/off of <iobj>", return the (non-fixed)
  2941.      *   contents of the indirect object.  Same goes for "take all in
  2942.      *   <iobj>", "take all on <iobj>", and "take all from <iobj>".
  2943.      */
  2944.     if (( prep=outPrep or prep=offPrep or prep=inPrep or prep=onPrep
  2945.      or prep=fromPrep ) and io<>nil )
  2946.     {
  2947.         rem := io.contents;
  2948.         i := 1;
  2949.         tot := length( rem );
  2950.         while ( i <= tot )
  2951.         {
  2952.             cur := rem[i];
  2953.             if ( not cur.isfixed ) ret := ret + cur;
  2954.         i := i + 1;
  2955.         }
  2956.             return( ret );
  2957.     }
  2958.  
  2959.         /*
  2960.      *   In the general case, return everything that's not fixed
  2961.      *   in the actor's location, or everything inside fixed containers
  2962.      *   that isn't itself fixed.
  2963.      */
  2964.         rem := actor.location.contents;
  2965.     tot := length( rem );
  2966.     i := 1;
  2967.         while ( i <= tot )
  2968.         {
  2969.         cur := rem[i];
  2970.             if ( cur.isfixed )
  2971.             {
  2972.                 if ((( cur.isopenable and cur.isopen ) or
  2973.                   ( not cur.isopenable )) and ( not cur.isactor ))
  2974.                 {
  2975.                     rem2 := cur.contents;
  2976.             tot2 := length( rem2 );
  2977.             j := 1;
  2978.                     while ( j <= tot2 )
  2979.                     {
  2980.                 cur2 := rem2[j];
  2981.                         if ( not cur2.isfixed and not cur2.notakeall )
  2982.             {
  2983.                 ret := ret + cur2;
  2984.             }
  2985.                         j := j + 1;
  2986.                     }
  2987.                 }
  2988.             }
  2989.             else if ( not cur.notakeall )
  2990.         {
  2991.             ret := ret + cur;
  2992.         }
  2993.  
  2994.         i := i + 1;            
  2995.         }
  2996.         return( ret );
  2997.     }
  2998. ;
  2999. plugVerb: deepverb
  3000.     verb = 'plug'
  3001.     sdesc = "plug"
  3002.     prepDefault = inPrep
  3003.     ioAction( inPrep ) = 'PlugIn'
  3004. ;
  3005. lookInVerb: deepverb
  3006.     verb = 'look in' 'look on'
  3007.     sdesc = "look in"
  3008.     doAction = 'Lookin'
  3009. ;
  3010. screwVerb: deepverb
  3011.     verb = 'screw'
  3012.     sdesc = "screw"
  3013.     ioAction( withPrep ) = 'ScrewWith'
  3014.     doAction = 'Screw'
  3015. ;
  3016. unscrewVerb: deepverb
  3017.     verb = 'unscrew'
  3018.     sdesc = "unscrew"
  3019.     ioAction( withPrep ) = 'UnscrewWith'
  3020.     doAction = 'Unscrew'
  3021. ;
  3022. turnVerb: deepverb
  3023.     verb = 'turn' 'rotate' 'twist'
  3024.     sdesc = "turn"
  3025.     ioAction( toPrep ) = 'TurnTo'
  3026.     ioAction( withPrep ) = 'TurnWith'
  3027.     doAction = 'Turn'
  3028. ;
  3029. switchVerb: deepverb
  3030.     verb = 'switch'
  3031.     sdesc = "switch"
  3032.     doAction = 'Switch'
  3033. ;
  3034. flipVerb: deepverb
  3035.     verb = 'flip'
  3036.     sdesc = "flip"
  3037.     doAction = 'Flip'
  3038. ;
  3039. turnOnVerb: deepverb
  3040.     verb = 'activate' 'turn on' 'switch on'
  3041.     sdesc = "turn on"
  3042.     doAction = 'Turnon'
  3043. ;
  3044. turnOffVerb: deepverb
  3045.     verb = 'turn off' 'deactivate' 'switch off'    // DMB: deavtiv + ate
  3046.     sdesc = "turn off"
  3047.     doAction = 'Turnoff'
  3048. ;
  3049. lookVerb: deepverb
  3050.     verb = 'look' 'l' 'look around'
  3051.     action( actor ) =
  3052.     {
  3053.         actor.location.lookAround( true );
  3054.     }
  3055. ;
  3056. sitVerb: deepverb
  3057.     verb = 'sit on' 'sit in' 'sit' 'sit down' 'sit downin' 'sit downon'
  3058.     sdesc = "sit on"
  3059.     doAction = 'Siton'
  3060. ;
  3061. lieVerb: deepverb
  3062.     verb = 'lie' 'lie on' 'lie in' 'lie down' 'lie downon' 'lie downin'
  3063.     sdesc = "lie on"
  3064.     doAction = 'Lieon'
  3065. ;
  3066. getOutVerb: deepverb
  3067.     verb = 'get out' 'get outof' 'get off' 'get offof'
  3068.     sdesc = "get out of"
  3069.     doAction = 'Unboard'
  3070.     doDefault( actor, prep, io ) =
  3071.     {
  3072.         if ( actor.location and actor.location.location )
  3073.             return( [] + actor.location );
  3074.         else return( [] );
  3075.     }
  3076. ;
  3077. boardVerb: deepverb
  3078.     verb = 'get in' 'get into' 'board' 'get on'
  3079.     sdesc = "get on"
  3080.     doAction = 'Board'
  3081. ;
  3082. againVerb: deepverb         // Required verb:  repeats last command.  No
  3083.                             // action routines are necessary; this one's
  3084.                             // handled internally by the parser.
  3085.     verb = 'again' 'g'
  3086. ;
  3087. waitVerb: deepverb
  3088.     verb = 'wait' 'z'
  3089.     action( actor ) =
  3090.     {
  3091.         "Time passes...\n";
  3092.     }
  3093. ;
  3094. iVerb: deepverb
  3095.     verb = 'inventory' 'i'
  3096.     action( actor ) =
  3097.     {
  3098.         if (length( actor.contents ))
  3099.         {
  3100.             "%You% %have% "; listcont( actor ); ". ";
  3101.         // DMB added the check for any contents
  3102.         if (listcontcont(actor, nil)) {
  3103.             P();
  3104.             listcontcont(actor, true);    // DMB added second param
  3105.         }
  3106.         }
  3107.     else
  3108.             "%You% %are% empty-handed.\n";
  3109.     }
  3110. ;
  3111. lookThruVerb: deepverb
  3112.     verb = 'look through' 'look thru'
  3113.     sdesc = "look through"
  3114.     doAction = 'Lookthru'
  3115. ;
  3116. attackVerb: deepverb
  3117.     verb = 'attack' 'kill' 'hit'
  3118.     sdesc = "attack"
  3119.     doAction = 'Attack'    // DMB
  3120.     prepDefault = withPrep
  3121.     ioAction( withPrep ) = 'AttackWith'
  3122. ;
  3123. eatVerb: deepverb
  3124.     verb = 'eat' 'consume'
  3125.     sdesc = "eat"
  3126.     doAction = 'Eat'
  3127. ;
  3128. drinkVerb: deepverb
  3129.     verb = 'drink' 'drink from'    // DMB: added 'drink from'
  3130.     sdesc = "drink"
  3131.     doAction = 'Drink'
  3132. ;
  3133. giveVerb: deepverb
  3134.     verb = 'give' 'offer'
  3135.     sdesc = "give"
  3136.     prepDefault = toPrep
  3137.     ioAction( toPrep ) = 'GiveTo'
  3138. ;
  3139. pullVerb: deepverb
  3140.     verb = 'pull'
  3141.     sdesc = "pull"
  3142.     doAction = 'Pull'
  3143. ;
  3144. readVerb: deepverb
  3145.     verb = 'read'
  3146.     sdesc = "read"
  3147.     doAction = 'Read'
  3148. ;
  3149. throwVerb: deepverb
  3150.     verb = 'throw' 'toss'
  3151.     sdesc = "throw"
  3152.     prepDefault = atPrep
  3153.     ioAction( atPrep ) = 'ThrowAt'
  3154.     ioAction( toPrep ) = 'ThrowTo'
  3155. ;
  3156. standOnVerb: deepverb
  3157.     verb = 'stand on'
  3158.     sdesc = "stand on"
  3159.     doAction = 'Standon'
  3160. ;
  3161. standVerb: deepverb
  3162.     verb = 'stand' 'stand up' 'get up'
  3163.     sdesc = "stand"
  3164.     action( actor ) =
  3165.     {
  3166.         if ( actor.location=nil or actor.location.location = nil )
  3167.             "%You're% already standing! ";
  3168.         else
  3169.         {
  3170.         actor.location.doUnboard( actor );
  3171.         }
  3172.     }
  3173. ;
  3174. helloVerb: deepverb
  3175.     verb = 'hello' 'hi' 'greetings'
  3176.     action( actor ) =
  3177.     {
  3178.         "Nice weather we've been having.\n";
  3179.     }
  3180. ;
  3181. showVerb: deepverb
  3182.     verb = 'show'
  3183.     sdesc = "show"
  3184.     prepDefault = toPrep
  3185.     ioAction( toPrep ) = 'ShowTo'
  3186. ;
  3187. cleanVerb: deepverb
  3188.     verb = 'clean'
  3189.     sdesc = "clean"
  3190.     ioAction( withPrep ) = 'CleanWith'
  3191.     doAction = 'Clean'
  3192. ;
  3193. sayVerb: deepverb
  3194.     verb = 'say'
  3195.     sdesc = "say"
  3196.     doAction = 'Say'
  3197. ;
  3198. yellVerb: deepverb
  3199.     verb = 'yell' 'shout' 'yell at' 'shout at'
  3200.     action( actor ) =
  3201.     {
  3202.         "%Your% throat is a bit sore now. ";
  3203.     }
  3204. ;
  3205. moveVerb: deepverb
  3206.     verb = 'move'
  3207.     sdesc = "move"
  3208.     ioAction( withPrep ) = 'MoveWith'
  3209.     ioAction( toPrep ) = 'MoveTo'
  3210.     doAction = 'Move'
  3211. ;
  3212. fastenVerb: deepverb
  3213.     verb = 'fasten' 'buckle' 'buckle up'
  3214.     sdesc = "fasten"
  3215.     doAction = 'Fasten'
  3216. ;
  3217. unfastenVerb: deepverb
  3218.     verb = 'unfasten' 'unbuckle'
  3219.     sdesc = "unfasten"
  3220.     doAction = 'Unfasten'
  3221. ;
  3222. unplugVerb: deepverb
  3223.     verb = 'unplug'
  3224.     sdesc = "unplug"
  3225.     ioAction( fromPrep ) = 'UnplugFrom'
  3226.     doAction = 'Unplug'
  3227. ;
  3228. lookUnderVerb: deepverb
  3229.     verb = 'look under' 'look beneath'
  3230.     sdesc = "look under"
  3231.     doAction = 'Lookunder'
  3232. ;
  3233. lookBehindVerb: deepverb
  3234.     verb = 'look behind'
  3235.     sdesc = "look behind"
  3236.     doAction = 'Lookbehind'
  3237. ;
  3238. typeVerb: deepverb
  3239.     verb = 'type'
  3240.     sdesc = "type"
  3241.     prepDefault = onPrep
  3242.     ioAction( onPrep ) = 'TypeOn'
  3243. ;
  3244. lockVerb: deepverb
  3245.     verb = 'lock'
  3246.     sdesc = "lock"
  3247.     ioAction( withPrep ) = 'LockWith'
  3248.     doAction = 'Lock'
  3249.     prepDefault = withPrep
  3250. ;
  3251. unlockVerb: deepverb
  3252.     verb = 'unlock'
  3253.     sdesc = "unlock"
  3254.     ioAction( withPrep ) = 'UnlockWith'
  3255.     doAction = 'Unlock'
  3256.     prepDefault = withPrep
  3257. ;
  3258. detachVerb: deepverb
  3259.     verb = 'detach' 'disconnect'
  3260.     prepDefault = fromPrep
  3261.     ioAction( fromPrep ) = 'DetachFrom'
  3262.     doAction = 'Detach'
  3263.     sdesc = "detach"
  3264. ;
  3265. /*
  3266.  * DMB
  3267.  */
  3268. sleepVerb: deepverb
  3269.     action(actor) = {
  3270.             "This is no time for loafing!";
  3271.     }
  3272.     
  3273.     verb = 'sleep' 'rest' 'loaf' 'nap' 'relax'
  3274. ;
  3275. pokeVerb: deepverb
  3276.     verb = 'poke' 'jab'
  3277.     sdesc = "poke"
  3278.     doAction = 'Poke'
  3279. ;
  3280. touchVerb: deepverb
  3281.     verb = 'touch'
  3282.     sdesc = "touch"
  3283.     doAction = 'Touch'
  3284. ;
  3285. moveNVerb: deepverb
  3286.     verb = 'move north' 'move n' 'push north' 'push n'
  3287.     sdesc = "move north"
  3288.     doAction = 'MoveN'
  3289. ;
  3290. moveSVerb: deepverb
  3291.     verb = 'move south' 'move s' 'push south' 'push s'
  3292.     sdesc = "move south"
  3293.     doAction = 'MoveS'
  3294. ;
  3295. moveEVerb: deepverb
  3296.     verb = 'move east' 'move e' 'push east' 'push e'
  3297.     sdesc = "move east"
  3298.     doAction = 'MoveE'
  3299. ;
  3300. moveWVerb: deepverb
  3301.     verb = 'move west' 'move w' 'push west' 'push w'
  3302.     sdesc = "move west"
  3303.     doAction = 'MoveW'
  3304. ;
  3305. moveNEVerb: deepverb
  3306.     verb = 'move northeast' 'move ne' 'push northeast' 'push ne'
  3307.     sdesc = "move northeast"
  3308.     doAction = 'MoveNE'
  3309. ;
  3310. moveNWVerb: deepverb
  3311.     verb = 'move northwest' 'move nw' 'push northwest' 'push nw'
  3312.     sdesc = "move northwest"
  3313.     doAction = 'MoveNW'
  3314. ;
  3315. moveSEVerb: deepverb
  3316.     verb = 'move southeast' 'move se' 'push southeast' 'push se'
  3317.     sdesc = "move southeast"
  3318.     doAction = 'MoveSE'
  3319. ;
  3320. moveSWVerb: deepverb
  3321.     verb = 'move southwest' 'move sw' 'push southwest' 'push sw'
  3322.     sdesc = "move southwest"
  3323.     doAction = 'MoveSW'
  3324. ;
  3325. centerVerb: deepverb
  3326.     verb = 'center'
  3327.     sdesc = "center"
  3328.     doAction = 'Center'
  3329. ;
  3330. /*
  3331.  * DMB search is synonymous with inspect.
  3332.  */
  3333. /*
  3334. searchVerb: deepverb
  3335.     verb = 'search'
  3336.     sdesc = "search"
  3337.     doAction = 'Search'
  3338. ;
  3339. */
  3340. /*
  3341.  *   Travel verbs  - these verbs allow the player to move about.
  3342.  *   All travel verbs have the property isTravelVerb set true.
  3343.  */
  3344. class travelVerb: deepverb
  3345.     isTravelVerb = true
  3346. ;
  3347. climbVerb: deepverb, travelVerb    // DMB: made this into a travelVerb
  3348.     verb = 'climb'
  3349.     travelDir( actor ) = { return(actor.location.climb); }
  3350.  
  3351.     sdesc = "climb"
  3352.     action( actor ) = { actor.travelTo(self.travelDir(actor)); }
  3353.     doAction = 'Climb'
  3354. ;
  3355. eVerb: travelVerb
  3356.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3357.     verb = 'e' 'east' 'go east'
  3358.     travelDir( actor ) = { return( actor.location.east ); }
  3359. ;
  3360. sVerb: travelVerb
  3361.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3362.     verb = 's' 'south' 'go south'
  3363.     travelDir( actor ) = { return( actor.location.south ); }
  3364. ;
  3365. nVerb: travelVerb
  3366.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3367.     verb = 'n' 'north' 'go north'
  3368.     travelDir( actor ) = { return( actor.location.north ); }
  3369. ;
  3370. wVerb: travelVerb
  3371.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3372.     verb = 'w' 'west' 'go west'
  3373.     travelDir( actor ) = { return( actor.location.west ); }
  3374. ;
  3375. neVerb: travelVerb
  3376.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3377.     verb = 'ne' 'northeast' 'go ne' 'go northeast'
  3378.     travelDir( actor ) = { return( actor.location.ne ); }
  3379. ;
  3380. nwVerb: travelVerb
  3381.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3382.     verb = 'nw' 'northwest' 'go nw' 'go northwest'
  3383.     travelDir( actor ) = { return( actor.location.nw ); }
  3384. ;
  3385. seVerb: travelVerb
  3386.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3387.     verb = 'se' 'southeast' 'go se' 'go southeast'
  3388.     travelDir( actor ) = { return( actor.location.se ); }
  3389. ;
  3390. swVerb: travelVerb
  3391.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3392.     verb = 'sw' 'southwest' 'go sw' 'go southwest'
  3393.     travelDir( actor ) = { return( actor.location.sw ); }
  3394. ;
  3395. inVerb: travelVerb
  3396.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3397.     verb = 'in' 'go in' 'enter'
  3398.     sdesc = "enter"
  3399.     doAction = 'Enter'
  3400.     travelDir( actor ) = { return( actor.location.in ); }
  3401. ;
  3402. outVerb: travelVerb
  3403.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3404.     verb = 'out' 'go out' 'exit' 'leave'
  3405.     travelDir( actor ) = { return( actor.location.out ); }
  3406. ;
  3407. dVerb: travelVerb
  3408.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3409.     verb = 'd' 'down' 'go down'
  3410.     travelDir( actor ) = { return( actor.location.down ); }
  3411. ;
  3412. uVerb: travelVerb
  3413.     action( actor ) = { actor.travelTo( self.travelDir( actor )); }
  3414.     verb = 'u' 'up' 'go up'
  3415.     travelDir( actor ) = { return( actor.location.up ); }
  3416. ;
  3417.  
  3418. /*
  3419.  *   sysverb:  A system verb.  Verbs of this class are special verbs that
  3420.  *   can be executed without certain normal validations.  For example,
  3421.  *   a system verb can be executed in a dark room.  System verbs are
  3422.  *   for operations such as saving, restoring, and quitting, which are
  3423.  *   not really part of the game.
  3424.  */
  3425. class sysverb: deepverb
  3426.     issysverb = true
  3427. ;
  3428. quitVerb: sysverb
  3429.     verb = 'quit'
  3430.     action( actor ) =
  3431.     {
  3432.         local yesno;
  3433.  
  3434.     /* XXX */
  3435.         "\bDo you really want to quit? (YES or NO) > ";
  3436.         yesno := yorn();
  3437.         "\b";
  3438.         if ( yesno = 1 )
  3439.         {
  3440.         silent_incscore(global.quitpoints); // points for quitting (neg.)
  3441.         scoreRank();    // DMB: moved here from XXX
  3442.             terminate();    // allow user good-bye message
  3443.         quit();
  3444.         }
  3445.         else
  3446.         {
  3447.             "Okay. ";
  3448.         }
  3449.     abort;
  3450.     }
  3451. ;
  3452. verboseVerb: sysverb
  3453.     verb = 'verbose'
  3454.     action( actor ) =
  3455.     {
  3456.         "Okay, now in VERBOSE mode.\n";
  3457.         global.verbose := true;
  3458.     Me.location.lookAround( true );
  3459.     abort;
  3460.     }
  3461. ;
  3462. terseVerb: sysverb
  3463.     verb = 'brief' 'terse'
  3464.     action( actor ) =
  3465.     {
  3466.         "Okay, now in TERSE mode.\n";
  3467.         global.verbose := nil;
  3468.     abort;
  3469.     }
  3470. ;
  3471. scoreVerb: sysverb
  3472.     verb = 'score' 'status'
  3473.     action( actor ) =
  3474.     {
  3475.         scoreRank();
  3476.     abort;
  3477.     }
  3478. ;
  3479. saveVerb: sysverb
  3480.     verb = 'save'
  3481.     sdesc = "save"
  3482.     doAction = 'Save'
  3483.     action( actor ) =
  3484.     {
  3485.         local savefile;
  3486.     
  3487.     savefile := askfile( 'File to save game in' );
  3488.     if ( savefile = nil or savefile = '' )
  3489.         "Failed. ";
  3490.     else if (save( savefile ))
  3491.         "Saved failed. ";
  3492.     else
  3493.         "Saved. ";
  3494.     abort;
  3495.     }
  3496. ;
  3497. restoreVerb: sysverb
  3498.     verb = 'restore'
  3499.     sdesc = "restore"
  3500.     doAction = 'Restore'
  3501.     action( actor ) =
  3502.     {
  3503.         local savefile;
  3504.     
  3505.     savefile := askfile( 'File to restore game from' );
  3506.     if ( savefile = nil or savefile = '' )
  3507.         "Failed. ";
  3508.     else if (restore( savefile ))
  3509.         "Restore failed. ";
  3510.     else
  3511.     {
  3512.         setscore( global.score, global.turnsofar );
  3513.         "Restored. ";
  3514.     }
  3515.     abort;
  3516.     }
  3517. ;
  3518. scriptVerb: sysverb
  3519.     verb = 'script'
  3520.     doAction = 'Script'
  3521.     action( actor ) =
  3522.     {
  3523.         local scriptfile;
  3524.     
  3525.     scriptfile := askfile( 'File to write transcript to' );
  3526.     if ( scriptfile = nil or scriptfile = '' )
  3527.         "Failed. ";
  3528.     else
  3529.     {
  3530.         logging( scriptfile );
  3531.         "Writing script file. ";
  3532.     }
  3533.     abort;
  3534.     }
  3535. ;
  3536. unscriptVerb: sysverb
  3537.     verb = 'unscript'
  3538.     action( actor ) =
  3539.     {
  3540.         logging( nil );
  3541.         "Script closed.\n";
  3542.         abort;
  3543.     }
  3544. ;
  3545. restartVerb: sysverb
  3546.     verb = 'restart'
  3547.     action( actor ) =
  3548.     {
  3549.         local yesno;
  3550.         while ( true )
  3551.         {
  3552.             "Are you sure you want to start over? (YES or NO) > ";
  3553.             yesno := yorn();
  3554.             if ( yesno = 1 )
  3555.             {
  3556.                 "\n";
  3557.         setscore( 0, 0 );
  3558.                 restart();
  3559.                 abort;
  3560.             }
  3561.             else if ( yesno = 0 )
  3562.             {
  3563.                 "\nOkay.\n";
  3564.                 abort;
  3565.             }
  3566.         }
  3567.     }
  3568. ;
  3569. versionVerb: sysverb
  3570.     verb = 'version'
  3571.     action( actor ) =
  3572.     {
  3573.         version.sdesc;
  3574.         abort;
  3575.     }
  3576. ;
  3577. debugVerb: sysverb
  3578.     verb = 'debug'
  3579.     action( actor ) =
  3580.     {
  3581.     if (debugTrace())
  3582.         "You can't think this game has any bugs left in it... ";
  3583.     abort;
  3584.     }
  3585. ;
  3586.  
  3587. undoVerb: sysverb
  3588.     verb = 'undo'
  3589.     action(actor) =
  3590.     {
  3591.     /* do TWO undo's - one for this 'undo', one for previous command */
  3592.     if (undo() and undo())
  3593.     {
  3594.         "(Undoing one command)\b";
  3595.         Me.location.lookAround(true);
  3596.         setscore(global.score, global.turnsofar);
  3597.     }
  3598.     else
  3599.         "No more undo information is available. ";
  3600.  
  3601.     abort;
  3602.     }
  3603. ;
  3604.  
  3605. /*
  3606. @Prep: object
  3607. A preposition.  The \tt preposition\ property specifies the
  3608. vocabulary word.
  3609. */
  3610. class Prep: object
  3611. ;
  3612.  
  3613. /*
  3614.  *   Various prepositions
  3615.  */
  3616. aboutPrep: Prep
  3617.     preposition = 'about'
  3618.     sdesc = "about"
  3619. ;
  3620. withPrep: Prep
  3621.     preposition = 'with'
  3622.     sdesc = "with"
  3623. ;
  3624. toPrep: Prep
  3625.     preposition = 'to'
  3626.     sdesc = "to"
  3627. ;
  3628. onPrep: Prep
  3629.     preposition = 'on' 'onto' 'downon' 'upon'
  3630.     sdesc = "on"
  3631. ;
  3632. inPrep: Prep
  3633.     preposition = 'in' 'into' 'downin'
  3634.     sdesc = "in"
  3635. ;
  3636. offPrep: Prep
  3637.     preposition = 'off' 'offof'
  3638.     sdesc = "off"
  3639. ;
  3640. outPrep: Prep
  3641.     preposition = 'out' 'outof'
  3642.     sdesc = "out"
  3643. ;
  3644. fromPrep: Prep
  3645.     preposition = 'from'
  3646.     sdesc = "from"
  3647. ;
  3648. betweenPrep: Prep
  3649.     preposition = 'between' 'inbetween'
  3650.     sdesc = "between"
  3651. ;
  3652. overPrep: Prep
  3653.     preposition = 'over'
  3654.     sdesc = "over"
  3655. ;
  3656. atPrep: Prep
  3657.     preposition = 'at'
  3658.     sdesc = "at"
  3659. ;
  3660. aroundPrep: Prep
  3661.     preposition = 'around'
  3662.     sdesc = "around"
  3663. ;
  3664. thruPrep: Prep
  3665.     preposition = 'through' 'thru'
  3666.     sdesc = "through"
  3667. ;
  3668. dirPrep: Prep
  3669.     preposition = 'north' 'south' 'east' 'west' 'up' 'down' 'northeast' 'ne'
  3670.                   'northwest' 'nw' 'southeast' 'se' 'southwest' 'sw'
  3671.     sdesc = "north"         // Shouldn't ever need this, but just in case
  3672. ;
  3673. underPrep: Prep
  3674.     preposition = 'under' 'beneath'
  3675.     sdesc = "under"
  3676. ;
  3677. behindPrep: Prep
  3678.     preposition = 'behind'
  3679.     sdesc = "behind"
  3680. ;
  3681.  
  3682. /*
  3683.  *   articles:  the "built-in" articles.  "The," "a," and "an" are
  3684.  *   defined.
  3685.  */
  3686. articles: object
  3687.     article = 'the' 'a' 'an'
  3688. ;
  3689.